home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / macros / eplain / xeplain.tex (.txt) < prev   
LaTeX Document  |  1994-04-29  |  86KB  |  2,008 lines

  1. % xeplain.tex: macros for nonformatting.  Written 1989--94 by (mostly)
  2. % Karl Berry.  These macros are in the public domain.
  3. % This is the ``extended plain'' TeX format that's described in
  4. % `eplain.texinfo', which you should have received with this file.  We
  5. % assume plain has been loaded.
  6. % N.B.: A version number is defined at the beginning and end of this file;
  7. % please change those numbers whenever the file is modified!
  8. % And don't modify the file under any circumstances; rename it first.
  9. % Some macros were written and/or suggested by Paul Abrahams.
  10. % Other sources (e.g., The TeXbook) are cited at the appropriate places.
  11. %% @texfile{
  12. %%   author = "Karl Berry",
  13. %%   version = "REPLACE-WITH-VERSION",
  14. %%   date = "REPLACE-WITH-DATE",
  15. %%   filename = "xeplain.tex",
  16. %%   email = "karl@cs.umb.edu",
  17. %%   address = "135 Center Hill Rd. // Plymouth, MA 02360"
  18. %%   checksum = "REPLACE-WITH-CHECKSUM",
  19. %%   codetable = "ISO/ASCII",
  20. %%   supported = "yes",
  21. %%   docstring = "This file defines macros that extend and expand on
  22. %%                plain TeX. eplain.tex is xeplain.tex and the other
  23. %%                source files with comments stripped; see the original
  24. %%                files for author credits, etc.  And please base diffs
  25. %%                or other contributions on xeplain.tex, not the
  26. %%                stripped-down eplain.tex.",
  27. % Category codes, etc.
  28. \def\makeactive#1{\catcode`#1 = \active \ignorespaces}%
  29. \chardef\letter = 11
  30. \chardef\other = 12
  31. % So we can have user-inaccessible control sequences.
  32. \edef\leftdisplays{\the\catcode`@}%
  33. \catcode`@ = \letter
  34. \let\@eplainoldatcode = \leftdisplays
  35. % Save miniscule amounts of memory and time by writing \toks@ii instead
  36. % of \toks2.
  37. \toksdef\toks@ii = 2
  38. % This macro is defined in The TeXbook, but it never made it
  39. % into plain TeX.  \dospecials is defined there, though.
  40. \def\uncatcodespecials{%
  41.    \def\do##1{\catcode`##1 = \other}%
  42.    \dospecials
  43. % Here is a way to do \let^^M = \cs, where the \let need not be global.
  44.    \makeactive\^^M %
  45.    \long\gdef\letreturn#1{\let^^M = #1}%
  46. % Swallow parameters, etc.
  47. \let\@eattoken = \relax  % Define this, so \eattoken can be used in \edef.
  48. \def\eattoken{\let\@eattoken = }%
  49. \def\gobble#1{}%
  50. \def\gobbletwo#1#2{}%
  51. \def\gobblethree#1#2#3{}%
  52. % We can't just use \empty as the identity function, since then outer
  53. % braces which would supposedly delimit the argument would define a group.
  54. \def\identity#1{#1}%
  55. % True if #1 is the empty string, i.e., called like `\ifempty{}'.
  56. \def\ifempty#1{\@@ifempty #1\@emptymarkA\@emptymarkB}%
  57. \def\@@ifempty#1#2\@emptymarkB{\ifx #1\@emptymarkA}%
  58. % Turn a definition into the characters that compose it.  See
  59. % ``Sanitizing control sequences under \write'', by Ron Whitney, TUGboat
  60. % 11(4), p.620.
  61. \def\@gobblemeaning#1:->{}%
  62. \def\sanitize{\expandafter\@gobblemeaning\meaning}%
  63. % From p.308 of the TeXbook.  This cannot be used in places where TeX
  64. % might be skipping tokens, e.g., in conditionals.
  65. \def\ifundefined#1{\expandafter\ifx\csname#1\endcsname\relax}%
  66. % \csname constructions come up an awful lot, so we save typing with the
  67. % following.  (But the extra macro expansion does take time, so we don't
  68. % use these in frequently-executed code.)
  69. \def\csn#1{\csname#1\endcsname}%
  70. \def\ece#1#2{\expandafter#1\csname#2\endcsname}%
  71. % \expandonce{TOKEN} abbreviates \expandafter\noexpand TOKEN.
  72. \def\expandonce{\expandafter\noexpand}%
  73. % Don't show our register allocations in the log.
  74. \let\@plainwlog = \wlog
  75. \let\wlog = \gobble
  76. % Make it convenient to put newlines in error messages.
  77. \newlinechar = `^^J
  78. % Sometimes it is convenient to have everything in the transcript file
  79. % and nothing on the terminal.  We don't just call \tracingall here,
  80. % since that produces some useless output on the terminal.
  81. \def\gloggingall{\begingroup \globaldefs = 1 \loggingall \endgroup}%
  82. \def\loggingall{\tracingcommands\tw@\tracingstats\tw@
  83.    \tracingpages\@ne\tracingoutput\@ne\tracinglostchars\@ne
  84.    \tracingmacros\tw@\tracingparagraphs\@ne\tracingrestores\@ne
  85.    \showboxbreadth\maxdimen\showboxdepth\maxdimen
  86. % Show the complete contents of boxes.
  87. \def\tracingboxes{\showboxbreadth = \maxdimen \showboxdepth = \maxdimen}%
  88. % Don't trace anything, except restore \showbox... to plain's values.
  89. \def\gtracingoff{\begingroup \globaldefs = 1 \tracingoff \endgroup}%
  90. \def\tracingoff{\tracingonline\z@\tracingcommands\z@\tracingstats\z@
  91.   \tracingpages\z@\tracingoutput\z@\tracinglostchars\z@
  92.   \tracingmacros\z@\tracingparagraphs\z@\tracingrestores\z@
  93.   \showboxbreadth5 \showboxdepth3
  94. % Definitions to produce actual `{' (et al.) characters in an output
  95. % file via \write.  We omit the line break after the first }, since we
  96. % have no comment character at that point.
  97. \begingroup
  98.   \catcode`\{ = 12 \catcode`\} = 12
  99.   \catcode`\[ = 1 \catcode`\] = 2
  100.   \gdef\lbracechar[{]%
  101.   \gdef\rbracechar[}]%
  102.   \catcode`\% = \other
  103.   \gdef\percentchar[%]\endgroup
  104. % In order to do anything with ^^L inside a macro, it must
  105. % be made non-\outer.
  106. \def^^L{\par}%
  107. % Leave horizontal mode (if we're in it), then insert a penalty.
  108. % And conversely.
  109. \def\vpenalty{\ifhmode\par\fi \penalty}%
  110. \def\hpenalty{\ifvmode\leavevmode\fi \penalty}%
  111. % Make \else usable in \loop.  From Victor Eijkhout's TeX by Topic (page
  112. % 104).  See also Alois Kabelschacht, TUGboat 8(2), page 184.
  113. \def\iterate{%
  114.   \let\next\relax
  115.   \body
  116.   \let\next\iterate
  117.   \fi
  118.   \next
  119. % Add #2 (which is expanded in an \edef) to the end of the definition of
  120. % #1 (which must be a previously-defined control sequence).  This is a
  121. % way to construct simple lists.
  122. \def\edefappend#1#2{%
  123.   \toks@ = \expandafter{#1}%
  124.   \edef#1{\the\toks@ #2}%
  125.  Hooks.
  126. % \hookaction{HOOK}{TOKENS} adds TOKENS to the list of actions for
  127. % HOOK.  We avoid defining a \toks register for each hook, although
  128. % maybe that isn't so important.
  129. % \hookappend and \hookprepend add TOKENS specificially to the end or
  130. % the beginning.  When the argument is used, \toks@ will be the previous
  131. % value of the hook, and \toks@ii the new tokens.
  132. \long\def\hookprepend{\@hookassign{\the\toks@ii \the\toks@}}%
  133. \long\def\hookappend{\@hookassign{\the\toks@ \the\toks@ii}}%
  134. \let\hookaction = \hookappend % either one should be ok
  135. % \@hookassign{LAST-DEF}{HOOK}{TOKENS} makes \toks@ the previous value
  136. % of HOOK, and \toks@ii TOKENS, and then assigns the new value using
  137. % LASTDEF.  We store the hook in a control sequence \@HOOKhook.
  138. \long\def\@hookassign#1#2#3{%
  139.   % Make \toks@ be the expansion (to one level) of \@HOOKhook, or empty.
  140.   \expandafter\ifx\csname @#2hook\endcsname \relax
  141.     % If \@HOOKhook was undefined, let it be empty.
  142.     \toks@ = {}%
  143.   \else
  144.     % Otherwise, expand it to one level.  We can't just assign from
  145.     % \expandafter{\csname ...} since then the \toks register would
  146.     % contain the control sequence, not its definition.
  147.     \expandafter\let\expandafter\temp \csname @#2hook\endcsname
  148.     \toks@ = \expandafter{\temp}%
  149.   \fi
  150.   \toks2 = {#3}% Don't expand the argument all the way.
  151.   \ece\edef{@#2hook}{#1}%
  152. % \hookactiononce{HOOK}\CS adds `\global\let\CS=\relax' to the
  153. % definition of \CS, then adds to HOOK.  Thus, \CS is expanded the next
  154. % time HOOK is called, but then it goes away.  This only works if \CS is
  155. % expandable, though.
  156. \long\def\hookactiononce#1#2{%
  157.   \edefappend#2{\global\let\noexpand#2\relax}
  158.   \hookaction{#1}#2%
  159. % \hookrun{HOOKNAME} runs whatever actions have been defined for HOOK.
  160. \def\hookrun#1{%
  161.   \expandafter\ifx\csname @#1hook\endcsname \relax \else
  162.     % Isn't this fun?  We want to get rid of the \fi before expanding
  163.     % the actions, so that they can read what's coming up next.
  164.     \def\temp{\csname @#1hook\endcsname}%
  165.     \expandafter\temp
  166.   \fi
  167.  Properties a la Lisp.
  168. % \setproperty{ATOM}{PROPNAME}{VALUE} defines the property PROPNAME on the
  169. % ``atom'' ATOM to have VALUE.
  170. \def\setproperty#1#2#3{\ece\edef{#1@p#2}{#3}}%
  171. % \getproperty{ATOM}{PROPNAME} expands to the value of the property
  172. % PROPNAME on ATOM, or to nothing (i.e., \empty), if the property isn't
  173. % present.
  174. \def\getproperty#1#2{%
  175.   \expandafter\ifx\csname#1@p#2\endcsname\relax
  176.   % then \empty
  177.   \else \csname#1@p#2\endcsname
  178.   \fi
  179.  Macros to support BibTeX are in a separate file, btxmac.tex.
  180. % (They are maintained separately, too, by Oren Patashnik,
  181. % opbibtex@cs.stanford.edu.)  btxmac.tex also defines other macros we
  182. % want to use and make available.
  183. % But not all people want to read the BibTeX macros, because of either
  184. % space or time considerations.  Therefore, we look for \nobibtex,
  185. % which, if defined, causes btxmac.tex not to be read.  But we still
  186. % have to get \tokstostring et al. defined---so eplain.tex contains
  187. % those definitions, automatically edited in from btxmac.tex.  All the
  188. % documentation has been removed, so you must read btxmac.tex if you
  189. % want the comments.
  190. % We want to give a slightly different message than btxmac if no .aux
  191. % file exists (unless the person using us has already define some
  192. % message, possibly empty.)
  193. \ifx\@undefinedmessage\@undefined
  194.   \def\@undefinedmessage
  195.     {No .aux file; I won't warn you about undefined labels.}%
  196. % We use a token register to define all the BibTeX definitions, to avoid
  197. % problems with the \if... constructions when they are conditionally
  198. % read.
  199. %% [[[here is the first set of common definitions from btxmac]]]
  200. \toks0 = {%
  201.   %% [[[here are the BibTeX-specific definitions from btxmac]]]
  202. \ifx\nobibtex\@undefined \the\toks0 \fi
  203. %% [[[here is the second set of common definitions from btxmac]]]
  204. % Here are the control sequences that btxmac.tex defines using an @,
  205. % because btxmac.tex wants to absolutely minimize the chance of
  206. % conflicts.  But these control sequence implement documented features
  207. % of eplain, so we want to allow people to use them without the @.
  208. \let\auxfile = \@auxfile
  209. \let\for = \@for
  210. \let\futurenonspacelet = \@futurenonspacelet
  211. \def\iffileexists{\if@fileexists}%
  212. \let\innerdef = \@innerdef
  213. \let\innernewcount = \@innernewcount
  214. \let\innernewdimen = \@innernewdimen
  215. \let\innernewif = \@innernewif
  216. \let\innernewwrite = \@innernewwrite
  217. \let\linenumber = \@linenumber
  218. \let\readauxfile = \@readauxfile
  219. \let\spacesub = \@spacesub
  220. \let\testfileexistence = \@testfileexistence
  221. \let\writeaux = \@writeaux
  222. % btxmac.tex defines \innerdef.  Let's use it to make an abbreviation
  223. % for \innerdef\inner<name>{<name>}.
  224. \def\innerinnerdef#1{\expandafter\innerdef\csname inner#1\endcsname{#1}}%
  225. % Use that in turn to make non-outer versions of the rest of plain TeX's
  226. % allocation macros.  (btxmac.tex already did a few of them.)
  227. \innerinnerdef{newbox}%
  228. \innerinnerdef{newfam}%
  229. \innerinnerdef{newhelp}%
  230. \innerinnerdef{newinsert}%
  231. \innerinnerdef{newlanguage}%
  232. \innerinnerdef{newmuskip}%
  233. \innerinnerdef{newread}%
  234. \innerinnerdef{newskip}%
  235. \innerinnerdef{newtoks}%
  236. % Besides doing a \write to the aux file, we also need to do an
  237. % \immediate\write.
  238. \def\immediatewriteaux#1{%
  239.   \ifx\noauxfile\@undefined
  240.     \immediate\write\@auxfile{#1}%
  241.   \fi
  242.  Macros that produce output.
  243. % \obeywhitespace makes both end-of-lines and spaces in the input be
  244. % respected in the output.  Even spaces at the beginning of lines turn
  245. % into blank space the size of the natural space of the current font.
  246. % The reason why plain TeX's \obeyspaces does not do this last is that
  247. % it produces actual space characters, i.e., glue, and glue is discarded
  248. % at a(n output) line break, and so if line breaks in the input are
  249. % line breaks in the output...
  250. % Tabs are not affected; they will still produce glue (a single space).
  251. \begingroup
  252.    \makeactive\^^M \makeactive\ % No spaces or ^^M's from here on.
  253. \gdef\obeywhitespace{%
  254. \makeactive\^^M\def^^M{\par\futurelet\next\@finishobeyedreturn}%
  255. \makeactive\ \let =\ %
  256. % The group we use here is the one \obeywhitespace must be enclosed in.
  257. % If we don't do this, then if the obeyed stuff ends in a newline, the
  258. % indent produced by the definition of ^^M will make that line indented,
  259. % even if it isn't the end of the paragraph.
  260. \aftergroup\@removebox%
  261. \futurelet\next\@finishobeywhitespace%
  262. % \@finishobeywhitespace eats any spaces and/or the end-of-line after
  263. % the \obeywhitespace command itself.  The group here is the one that it
  264. % itself creates.
  265. \gdef\@finishobeywhitespace{{%
  266. \ifx\next %
  267. \aftergroup\@obeywhitespaceloop%
  268. \else\ifx\next^^M%
  269. \aftergroup\gobble%
  270. \fi\fi}}%
  271. % \@finishobeyedreturn is invoked at the end of every input line.  We
  272. % check if the next thing is also a return, and, if so, insert extra
  273. % space.  Then we start the next line.
  274. \gdef\@finishobeyedreturn{%
  275. \ifx\next^^M\vskip\blanklineskipamount\fi%
  276. \indent%
  277. \endgroup
  278. % The argument here is the space that we are supposed to eat after the
  279. % \obeywhitespace command.
  280. \def\@obeywhitespaceloop#1{\futurelet\next\@finishobeywhitespace}%
  281. % This removes the last box, if it was a empty box of width \parindent.
  282. % We might have been called inside a \vbox, so we have to test if we are
  283. % in horizontal mode before using \lastbox.
  284. \def\@removebox{%
  285.   \ifhmode
  286.     \setbox0 = \lastbox
  287.     \ifdim\wd0=\parindent
  288.       \setbox2 = \hbox{\unhbox0}%
  289.       \ifdim\wd2=0pt
  290.         % Don't put it back: it was an indentation box.
  291.         % This \ignorespaces ignores spaces after the group.
  292.         \ignorespaces
  293.       \else
  294.         \box2 % Put it back: it wasn't empty.
  295.       \fi
  296.     \else
  297.        \box0 % Put it back: it wasn't the right width.
  298.     \fi
  299.   \fi
  300. % We allow for extra (possibly negative) space when we hit blank lines.
  301. \newskip\blanklineskipamount
  302. \blanklineskipamount = 0pt
  303. % A good way to print fractions in text when you don't want
  304. % to use \over (which should be most of the time), and yet
  305. % just `1/2' doesn't look right.  (From the TeXbook,
  306. % the answer to exercise 11.6, p.311.)
  307. \def\frac#1/#2{\leavevmode
  308.    \kern.1em \raise .5ex \hbox{\the\scriptfont0 #1}%
  309.    \kern-.1em $/$%
  310.    \kern-.15em \lower .25ex \hbox{\the\scriptfont0 #2}%
  311. % The `e' just means `Eplain', as in `Eplain's hrule'.  The advantage
  312. % to using these is that you can change the default thickness.
  313. \newdimen\hruledefaultheight  \hruledefaultheight = 0.4pt
  314. \newdimen\hruledefaultdepth   \hruledefaultdepth = 0.0pt
  315. \newdimen\vruledefaultwidth   \vruledefaultwidth = 0.4pt
  316. \def\ehrule{\hrule height\hruledefaultheight depth\hruledefaultdepth}%
  317. \def\evrule{\vrule width\vruledefaultwidth}%
  318. % The texnames.sty and path.sty files included below were originally
  319. % written by Nelson Beebe and Philip Taylor, respectively. See the
  320. % complete source files (e.g., in this distribution) for comments.
  321. %% [[[include texnames.sty]]]
  322. %% [[[include path.sty]]]
  323. % A square box, suitable for being a marker in lists.
  324. \def\blackbox{\vrule height .8ex width .6ex depth -.2ex \relax}% square bullet
  325. % From p.311 of the TeXbook.
  326. % Make an unfilled rectangle with the dimensions of \box0.  #1 is the
  327. % height of the rules, #2 the depth (i.e., the thicknesses).
  328. \def\makeblankbox#1#2{%
  329.   \ifvoid0
  330.     \errhelp = \@makeblankboxhelp
  331.     \errmessage{Box 0 is void}%
  332.   \fi
  333.   \hbox{\lower\dp0
  334.     \vbox{\hidehrule{#1}{#2}%
  335.       \kern -#1% overlap rules
  336.       \hbox to \wd0{\hidevrule{#1}{#2}%
  337.         \raise\ht0\vbox to #1{}% vrule height
  338.         \lower\dp0\vtop to #1{}% vrule depth
  339.         \hfil\hidevrule{#2}{#1}%
  340.       }%
  341.       \kern-#1\hidehrule{#2}{#1}%
  342.     }%
  343. \newhelp\@makeblankboxhelp{Assigning to the dimensions of a void^^J%
  344.   box has no effect.  Do `\string\setbox0=\string\null' before you^^J%
  345.   define its dimensions.}%
  346. % Produce an hrule with height #1 and depth #2, and insert kerning so it
  347. % doesn't change the current position.
  348. \def\hidehrule#1#2{\kern-#1\hrule height#1 depth#2 \kern-#2}%
  349. % Produce a vrule with width #1+#2, kerning so as not to change the
  350. % current position.
  351. \def\hidevrule#1#2{%
  352.   \kern-#1%
  353.   \dimen@=#1\advance\dimen@ by #2%
  354.   \vrule width\dimen@
  355.   \kern-#2%
  356. % The \boxit macro from the TeXbook, trivially generalized to allow
  357. % something other than 3pt around the TeX box being boxed.
  358. \newdimen\boxitspace \boxitspace = 3pt
  359. \long\def\boxit#1{%
  360.   \vbox{%
  361.     \ehrule
  362.     \hbox{%
  363.       \evrule
  364.       \kern\boxitspace
  365.       \vbox{\kern\boxitspace \parindent = 0pt #1\kern\boxitspace}%
  366.       \kern\boxitspace
  367.       \evrule
  368.     }%
  369.     \ehrule
  370. % Produce the written-out form of a number.
  371. \def\numbername#1{\ifcase#1%
  372.    zero%
  373.    \or one%
  374.    \or two%
  375.    \or three%
  376.    \or four%
  377.    \or five%
  378.    \or six%
  379.    \or seven%
  380.    \or eight%
  381.    \or nine%
  382.    \or ten%
  383.    \or #1%
  384.    \fi
  385. % The following arrow macros were written by Steven Smith. See arrow.tex.
  386. \let\@plainnewif = \newif
  387. \let\@plainnewdimen = \newdimen
  388. \let\newif = \innernewif
  389. \let\newdimen = \innernewdimen
  390. \edef\@eplainoldandcode{\the\catcode`& }%
  391. \catcode`& = 11
  392. \toks0 = {%
  393.   %% [[[include arrow1]]]
  394. \catcode`& = 4
  395. \toks2 = {%
  396.   %% [[[include arrow2]]]
  397. \let\newif = \@plainnewif
  398. \let\newdimen = \@plainnewdimen
  399. \ifx\noarrow\@undefined \the\toks0 \the\toks2 \fi
  400. \catcode`& = \@eplainoldandcode
  401.  Environments.
  402. % Define an ``environment'': arbitrary text, enclosed by \begingroup and
  403. % \endgroup.  But you get to label the group, so that if you forget an
  404. % \environment or an \endenvironment, you will probably get an error
  405. % message about it.
  406. % Since the environment names appear in \errmessage arguments, it's best
  407. % to keep them to `letter' and `other' characters.  I suppose we could
  408. % call \tokstostring to allow more general labels.
  409. % These macros improve slightly on the answer to exercise 5.7 in
  410. % The TeXbook, by making some checks on \begingroup and \endgroup, as
  411. % well as just making sure \environment and \endenvironment's match.
  412. \def\environment#1{%
  413.    \ifx\@groupname\@undefined\else
  414.       % This gets invoked if we have two \environments (and no matching
  415.       % \endenvironment to the first) with an \endgroup in between.
  416.       \errhelp = \@unnamedendgrouphelp
  417.       \errmessage{`\@groupname' was not closed by \string\endenvironment}%
  418.    \fi
  419.    % Use \edef in case we are passed a macro that contains the name,
  420.    % instead of the name.
  421.    \edef\@groupname{#1}%
  422.    \begingroup
  423.       \let\@groupname = \@undefined
  424. \def\endenvironment#1{%
  425.    \endgroup
  426.    \edef\@thearg{#1}%
  427.    \ifx\@groupname\@thearg
  428.    \else
  429.       \ifx\@groupname\@undefined
  430.          % Unfortunately, one gets an `extra \endgroup' message before
  431.          % seeing this.  But we have to restore \@groupname, so I see no
  432.          % alternative. 
  433.          \errhelp = \@isolatedendenvironmenthelp
  434.          \errmessage{Isolated \string\endenvironment\space for `#1'}%
  435.       \else
  436.          \errhelp = \@mismatchedenvironmenthelp
  437.          \errmessage{Environment `#1' ended, but `\@groupname' started}%
  438.          \endgroup % Probably a typo in the names.
  439.       \fi
  440.    \fi
  441.    \let\@groupname = \@undefined
  442. \newhelp\@unnamedendgrouphelp{Most likely, you just forgot an^^J%
  443.    \string\endenvironment.  Maybe you should try inserting another^^J%
  444.    \string\endgroup to recover.}%
  445. \newhelp\@isolatedendenvironmenthelp{You ended an environment X, but^^J%
  446.    no \string\environment{X} to start it is anywhere in sight.^^J%
  447.    You might also be at an \string\endenvironment\space that would match^^J%
  448.    a \string\begingroup, i.e., you forgot an \string\endgroup.}%
  449. \newhelp\@mismatchedenvironmenthelp{You started an environment named X, but^^J%
  450.    you ended one named Y.  Maybe you made a typo in one^^J%
  451.    or the other of the names?}%
  452. % The above sort of environment allows nesting.  But environments
  453. % shouldn't always be allowed to nest (like the \flushright,
  454. % \flushleft, and \center ones defined below).  Here are some macros to
  455. % help deal with that.
  456. % \checkenvironmentnesting goes at the beginning of a macro that is
  457. % going to define the environment.
  458. \newif\ifenvironment
  459. \def\checkenv{\ifenvironment \errhelp = \@interwovenenvhelp
  460.    \errmessage{Interwoven environments}%
  461.    \egroup \fi
  462. \newhelp\@interwovenenvhelp{Perhaps you forgot to end the previous^^J%
  463.    environment? I'm finishing off the current group,^^J%
  464.    hoping that will fix it.}%
  465.  Mathematics displays.
  466. % By default, TeX centers displayed material.  To get left-justified
  467. % displays, say \leftdisplays.  To go back to centered displays, say
  468. % \centereddisplays.
  469. % This is based on an approach developed by Donald Arseneau,
  470. % asnd@triumfrg.bitnet.
  471. \newtoks\previouseverydisplay
  472. \newdimen\leftdisplayindent
  473. \newif\if@leftdisplays
  474. \def\leftdisplays{%
  475.   % IF we've already been called, do nothing.
  476.   \if@leftdisplays\else
  477.     \previouseverydisplay = \everydisplay
  478.     \everydisplay = {\the\previouseverydisplay \leftdisplaysetup}%
  479.     %
  480.     % Since we don't want to start a group (the \leftdisplays might
  481.     % well continue to the end of the document), we have to explicitly
  482.     % save and restore everything we change.
  483.     \let\@save@maybedisableeqno = \@maybedisableeqno
  484.     \let\@saveeqno = \eqno
  485.     \let\@saveleqno = \leqno
  486.     \let\@saveeqalignno = \eqalignno
  487.     \let\@saveleqalignno = \leqalignno
  488.     \let\@maybedisableeqno = \relax
  489.     \def\eqno{\hfill\textstyle\enspace}%
  490.     \def\leqno{%
  491.       \hfill
  492.       \hbox to0pt\bgroup
  493.         \kern-\displaywidth
  494.         \kern-\displayindent
  495.         $\aftergroup\@leftleqnoend
  496.     }%
  497.     \@redefinealignmentdisplays
  498.     \@leftdisplaystrue
  499.   \fi
  500. \def\centereddisplays{%
  501.   % If \leftdisplays hasn't been called, don't try to restore all the
  502.   % stuff it changes.
  503.   \if@leftdisplays
  504.     \everydisplay = \previouseverydisplay
  505.     \let\@maybedisableeqno = \@save@maybedisableeqno
  506.     \let\eqno = \@saveeqno
  507.     \let\leqno = \@saveleqno
  508.     \let\eqalignno = \@saveeqalignno
  509.     \let\leqalignno = \@saveleqalignno
  510.     \@leftdisplaysfalse
  511.   \fi
  512. \def\leftdisplaysetup{%
  513.   \hbox to\displaywidth\bgroup
  514.     \strut
  515.     \dimen@ = \parindent
  516.       \advance\dimen@ by \leftdisplayindent 
  517.       \advance\dimen@ by \leftskip
  518.     \hskip\dimen@
  519.     % We can't use \displayindent all along, because then we would
  520.     % \hskip by the above plus \hangindent or \parshape indentation.
  521.     % See p.188.
  522.     \advance\displayindent by \dimen@
  523.     \advance\displaywidth by -\parindent
  524.       \advance\displaywidth by -\leftdisplayindent
  525.       \advance\displaywidth by -\leftskip
  526.     $%
  527.     %
  528.     % If we do a \noalign inside an \eqalignno, we will be in horizontal
  529.     % mode, and the line will be as wide as \hsize.  This will cause an
  530.     % overfull alignment, since we also have to fit the indentation in,
  531.     % before the alignment.
  532.     \advance\hsize by -\displayindent
  533.     %
  534.     \aftergroup\@lefteqend
  535.     \displaystyle
  536. \def\@lefteqend{\hfil\egroup$}% gets inserted between the ending $$
  537. \def\@leftleqnoend{\hss \egroup$}%
  538. % Since the equation is typeset in math mode and not display math mode,
  539. % \halign is illegal.  So we use \vcenter, a la \eqalign, to make the
  540. % \halign legal.  Also, we remove the \hfil from the left of the
  541. % template, to make the display come out flush left.
  542. \def\@redefinealignmentdisplays{%
  543.   \def\displaylines##1{\displ@y
  544.     \vcenter{%
  545.       % We add another \hfil outside math mode in this template to cure
  546.       % underfull hboxes that sometimes result (from big fractions as in
  547.       % exercise 19.19).  I'm not sure why DEK does \halign{\hbox to...}
  548.       % instead of just \halign to... here.
  549.       \halign{\hbox to\displaywidth{$\@lign\displaystyle####\hfil$\hfil}\crcr
  550.               ##1\crcr}}}%
  551.   \def\eqalignno##1{\displ@y
  552.     \let\noalign = \@lefteqalignonoalign
  553.     \vcenter{%
  554.       \halign to\displaywidth{%
  555.          \hfil $\@lign\displaystyle{####}$\tabskip\z@skip
  556.         &$\@lign\displaystyle{{}####}$\hfil\tabskip\centering
  557.         &\llap{$\@lign####$}\tabskip\z@skip\crcr
  558.         ##1\crcr}}}%
  559.   \def\leqalignno##1{\displ@y
  560.     % Don't use the \eqno in \eqdef.
  561.     \let\eqno = \relax
  562.     \vcenter{%
  563.       \halign to\displaywidth{%
  564.          \hfil$\@lign\displaystyle{####}$\tabskip\z@skip
  565.         &$\@lign\displaystyle{{}####}$\hfil\tabskip\centering
  566.         &\kern-\displaywidth
  567.          \rlap{\kern-\displayindent $\@lign####$}%
  568.          \tabskip\displaywidth\crcr
  569.         ##1\crcr}}}%
  570. % \noalign is typically used to insert a few words (`and', for example)
  571. % between two aligned equations.  So I don't think the \noaligned
  572. % material should be indented.  Since \noalign takes <vertical mode
  573. % material>, we would end up with double indentation, anyway: one
  574. % because we're indenting the whole display, and one at the start of the
  575. % <v.m.m.>.  (If you want to change any of this, you can put something in
  576. % \@everynoalign.)  So, we use this definition for \noalign in a
  577. % left-justified \eqalignno:
  578. \let\@primitivenoalign = \noalign
  579. \newtoks\@everynoalign
  580. \def\@lefteqalignonoalign#1{%
  581.   \@primitivenoalign{%
  582.     % Is it right to set \leftskip=0pt first, thus perhaps making this
  583.     % work in lists and so forth?  We just compensate for the other ways
  584.     % the display is indented here.
  585.     \advance\leftskip by -\parindent
  586.     \advance\leftskip by -\leftdisplayindent
  587.     \parskip = 0pt
  588.     %
  589.     % We use \parindent=0pt instead of \noindent because the latter
  590.     % starts unrestricted horizontal mode, which means the alignment
  591.     % we're inside will wind up being as wide as the page.  When the arg
  592.     % is just vertical material, this is wrong.  For example, using
  593.     % \matrix inside \eqalignno fails if \noindent is used.
  594.     \parindent = 0pt
  595.     \the\@everynoalign
  596.     #1%
  597.  Time macros.
  598. % TeX sets \time, \day, \month, and \year when it begins.  (And does not
  599. % update them as it runs!)
  600. % \monthname produces the name of the month, abbreviated to three
  601. % letters.  The primitive \month should never be zero.
  602. \def\monthname{%
  603.    \ifcase\month
  604.       \or Jan\or Feb\or Mar\or Apr\or May\or Jun%
  605.       \or Jul\or Aug\or Sep\or Oct\or Nov\or Dec%
  606.    \fi
  607. % \fullmonthname is like \monthname, except it doesn't abbreviate.
  608. \def\fullmonthname{%
  609.    \ifcase\month
  610.       \or January\or February\or March\or April\or May\or June%
  611.       \or July\or August\or September\or October\or November\or December%
  612.    \fi
  613. % \timestring produces the current time, in a format like `1:14 p.m.'.
  614. \def\timestring{\begingroup
  615.    \count0 = \time
  616.    \divide\count0 by 60
  617.    \count2 = \count0   % The hour, from zero to 23.
  618.    \count4 = \time
  619.    \multiply\count0 by 60
  620.    \advance\count4 by -\count0   % The minute, from zero to 59.
  621.    % But we need the minutes with a leading zero, if necessary.
  622.    \ifnum\count4<10
  623.       \toks1 = {0}%
  624.    \else
  625.       \toks1 = {}%
  626.    \fi
  627.    % 
  628.    % Convert the hour into `a.m.' or `p.m.', and make it mod 12.
  629.    \ifnum\count2<12
  630.       \toks0 = {a.m.}%
  631.    \else
  632.       \toks0 = {p.m.}%
  633.       \advance\count2 by -12
  634.    \fi
  635.    % If it's midnight, call it `12', not `0'.
  636.    \ifnum\count2=0
  637.       \count2 = 12
  638.    \fi
  639.    % Produce the output.
  640.    \number\count2:\the\toks1 \number\count4 \thinspace \the\toks0
  641. \endgroup}%
  642. % \timestamp produces a text string for the whole thing like
  643. % `23 Apr 1964  1:14 p.m.'.
  644. \def\timestamp{\number\day\space\monthname\space\number\year\quad\timestring}%
  645. % \today produces the current date, as in `23 April 1964'.
  646. \def\today{\the\day\ \fullmonthname\ \the\year}%
  647.  (Typographical) lists.
  648. % These macros can produce numbered or unnumbered lists.
  649. % You can change the spacing by assigning new values to these registers.
  650. % They are used by both kinds of lists.  \listleftindent is relative to
  651. % the current paragraph indentation, while \listrightindent is an
  652. % absolute value.  I do this for two reasons: (1) it is more useful, if not
  653. % more ``logical'', to make list indentation depend on the paragraph
  654. % indentation; (2) footnotes do not work if \parindent is zero, and
  655. % having a footnote in a list item is perfectly reasonable.
  656. % If you change \baselineskip and want \abovelistskip and \belowlistskip
  657. % to retain their meanings here, you will have to reassign to them.  The
  658. % \baselineskip here is the value at the time eplain.tex is read, i.e.,
  659. % 12pt (most likely).
  660. % If the items in your lists are very long, you might want to
  661. % make \interitemskipamount nonzero.  
  662. \newskip\abovelistskipamount      \abovelistskipamount = .5\baselineskip
  663.   \newcount\abovelistpenalty      \abovelistpenalty    = 10000
  664.   \def\abovelistskip{\vpenalty\abovelistpenalty \vskip\abovelistskipamount}%
  665. \newskip\interitemskipamount      \interitemskipamount = 0pt
  666.   \newcount\belowlistpenalty      \belowlistpenalty    = -50
  667.   \def\belowlistskip{\vpenalty\belowlistpenalty \vskip\belowlistskipamount}%
  668. \newskip\belowlistskipamount      \belowlistskipamount = .5\baselineskip
  669.   \newcount\interitempenalty      \interitempenalty    = 0
  670.   \def\interitemskip{\vpenalty\interitempenalty \vskip\interitemskipamount}%
  671. \newdimen\listleftindent    \listleftindent = 0pt
  672. \newdimen\listrightindent   \listrightindent = 0pt        
  673. \let\listmarkerspace = \enspace
  674. % To do arbitrary things at the start of each list:
  675. \newtoks\everylist
  676. % If you want no space between items for a particular list
  677. % (perhaps because the items in it are short), you can say,
  678. % e.g., \numberedlist\listcompact.
  679. \def\listcompact{\interitemskipamount = 0pt \relax}%
  680. % This is called to set up the parameters by both sorts of lists.
  681. % Because we set \rightskip, we finish off the current paragraph.
  682. \newdimen\@listindent
  683. \def\beginlist{%
  684.   % Insert the space above this list, before we change \leftskip
  685.   % (because the \vskip in here might be what ends the paragraph).
  686.   \abovelistskip
  687.   \@listindent = \parindent
  688.   \advance\@listindent by \listleftindent
  689.   % \leftskip shifts nested lists to the right on the page.
  690.   \advance\leftskip by \@listindent
  691.   \advance\rightskip by \listrightindent
  692.   % We always need \itemnumber, so we can know whether an item is the
  693.   % first one or not.
  694.   \itemnumber = 1
  695.   \the\everylist
  696. % A list item, for both kinds of lists.
  697. \def\li{\@getoptionalarg\@finli}%
  698. \def\@finli{%
  699.   \ifx\@optionalarg\empty \else
  700.     \expandafter\writeitemxref\expandafter{\@optionalarg}%
  701.   \fi
  702.   \ifnum\itemnumber=1 \else \interitemskip \fi
  703.   \printitem
  704.   \advance\itemnumber by 1
  705.   \advance\itemletter by 1
  706.   \advance\itemromannumeral by 1
  707.   % Just in case somebody creeps in with an argument or something.
  708.   \ignorespaces
  709. % \writeitemxref{LABEL} writes out a definition for LABEL to be \marker
  710. % for the aux file.
  711. \def\writeitemxref#1{\definexref{#1}\marker{item}}%
  712. % \printitem is used to print items by both sorts of lists.  A \par gets
  713. % produced before every item -- even the first one.  We also want to
  714. % make paragraphs after the first appear to be indented -- i.e., they
  715. % will have double indentation.  It is usually bad exposition to have
  716. % lists with multiparagraph items, but sometimes it is unavoidable.
  717. \def\printitem{%
  718.   \par
  719.   \vskip-\parskip
  720.   \noindent
  721.   \printmarker\marker
  722. % Output the list marker.
  723. \def\printmarker#1{\llap{\marker \enspace}}%
  724. % Common ending.
  725. \def\endlist{\belowlistskip}%
  726. % \numberedlist produces items which are numbered sequentially, starting
  727. % from one.  You start items with \li (`list item').  End the list with
  728. % \endnumberedlist.
  729. % A nested \numberedlist produces items labelled `(a)', `(b)', etc.  A
  730. % doubly (and deeper) nested \numberedlist labels items with `*'.
  731. % These registers keep track of where we are.
  732. \newcount\numberedlistdepth
  733. \newcount\itemnumber
  734. \newcount\itemletter
  735. \newcount\itemromannumeral
  736. \def\numberedmarker{%
  737.   \ifcase\numberedlistdepth
  738.       (impossible)%
  739.   \or \printitemnumber
  740.   \or \printitemletter
  741.   \or \printitemromannumeral
  742.   \else *%
  743.   \fi
  744. % These produce the text of the labels.  We use \the\itemletter so that
  745. % the value will expand.
  746. \def\printitemnumber{\number\itemnumber}%
  747. \def\printitemletter{\char\the\itemletter}%
  748. \def\printitemromannumeral{\romannumeral\itemromannumeral}%
  749. \def\numberedprintmarker#1{\llap{#1) \listmarkerspace}}%
  750. \def\numberedlist{\environment{@numbered-list}%
  751.   % This is set back to zero by getting to the end of the group.
  752.   \advance\numberedlistdepth by 1
  753.   \itemletter = `a
  754.   \itemromannumeral = 1
  755.   \beginlist
  756.   \let\marker = \numberedmarker
  757.   \let\printmarker = \numberedprintmarker
  758. \def\endnumberedlist{%
  759.   \par
  760.   \endenvironment{@numbered-list}%
  761.   \endlist
  762. % Allow synonyms for \numberedlist.
  763. \let\orderedlist = \numberedlist
  764. \let\endorderedlist = \endnumberedlist
  765. % \unorderedlist produces items which are labelled with bullets.  You
  766. % start an item with \li, just as with numbered lists.  You end the list
  767. % with \endunorderedlist.
  768. % A nested \unorderedlist produces items labelled with em-dashes.  A
  769. % doubly (and deeper) nested \unorderedlist uses `*'.
  770. \newcount\unorderedlistdepth
  771. \def\unorderedmarker{%
  772.   \ifcase\unorderedlistdepth
  773.       (impossible)%
  774.   \or \blackbox
  775.   \or ---%
  776.   \else *%
  777.   \fi
  778. \def\unorderedprintmarker#1{\llap{#1\listmarkerspace}}%
  779. \def\unorderedlist{\environment{@unordered-list}%
  780.   \advance\unorderedlistdepth by 1
  781.   \beginlist
  782.   \let\marker = \unorderedmarker
  783.   \let\printmarker = \unorderedprintmarker
  784. \def\endunorderedlist{%
  785.   \par
  786.   \endenvironment{@unordered-list}%
  787.   \endlist
  788.  Verbatim listing.
  789. % ... well, almost verbatim.  We assume the font \tt has all the
  790. % characters that will appear.  Control characters, except for tabs and
  791. % form feeds (and returns) won't produce anything useful.  Tabs produce
  792. % a fixed amount of space, and form feeds produce a page break.
  793. % This is based on Knuth's ideas in Appendix D of the TeXbook, p. 380.
  794. % The argument should be a filename.
  795. % if you need to do something more for your particular fonts and/or
  796. % environment before the file is input, give a definition to
  797. % \setuplistinghook.  If you want line numbers on the output, you can
  798. % say \let\setuplistinghook = \linenumberedlisting.
  799. \def\listing#1{%
  800.    \par \begingroup
  801.    \@setuplisting
  802.    \setuplistinghook
  803.    \input #1
  804.    \endgroup
  805. \let\setuplistinghook = \relax
  806. \def\linenumberedlisting{%
  807.   \ifx\lineno\undefined \innernewcount\lineno \fi
  808.   \lineno = 0
  809.   \everypar = {\advance\lineno by 1 \printlistinglineno}%
  810. \def\printlistinglineno{\llap{[\the\lineno]\quad}}%
  811. % \uncatcodespecials must come before \obeywhitespace, lest a space
  812. % character in the input produce character 32 from the \tt font.
  813. \def\listingfont{\tt}%
  814. \def\@setuplisting{%
  815.    \uncatcodespecials
  816.    \obeywhitespace
  817.    \makeactive\`
  818.    \makeactive\^^I
  819.    \def^^L{\vfill\eject}%
  820.    \parskip = 0pt
  821.    \listingfont
  822. % Give definitions to the characters we want to be special.
  823. % Do ` separately, so can use ` in the \catcode commands elsewhere.
  824.    \makeactive\`
  825.    \gdef`{\relax\lq}% Defeat ligatures.
  826.    \makeactive\^^I
  827.    \gdef^^I{\hskip8\fontdimen2\font \relax}%
  828. % \verbatim ... |endverbatim typesets the ... in typewriter.  To produce a |
  829. % in the ..., use ||.  This macro was contributed by beebe@math.utah.edu.
  830. % Generalized to characters other than | by dorai@cs.rice.edu.
  831. \def\verbatimescapechar#1{%
  832.   \gdef\@makeverbatimescapechar{%
  833.     \@makeverbatimdoubleescape #1%
  834.     \catcode`#1 = 0
  835. \def\@makeverbatimdoubleescape#1{%
  836.   \catcode`#1 = \other
  837.   \begingroup
  838.     \lccode`\* = `#1%
  839.     \lowercase{\endgroup \ece\def*{*}}%
  840. \verbatimescapechar\|  % initially escapechar is |
  841. \def\verbatim{\begingroup
  842.   \uncatcodespecials
  843.   \obeywhitespace
  844.   \makeactive\` % make space character a single space, not stretchable
  845.   \@makeverbatimescapechar
  846.   \tt}
  847. \let\endverbatim = \endgroup
  848.  Table of contents, list of figures, etc.
  849. % Entries for the table of contents are recorded in \jobname.toc, which
  850. % we open for writing at the first \writetocentry or when \readtocfile
  851. % is invoked (after we read it, in the latter case).  Actually, we use
  852. % \tocfilebasename for the root of the filename to read; \jobname is
  853. % the default.
  854. \def\definecontentsfile#1{%
  855.   \ece\innernewwrite{#1file}%
  856.   \ece\innernewif{if@#1fileopened}%
  857.   \ece\let{#1filebasename} = \jobname
  858.   \ece\def{open#1file}{\opencontentsfile{#1}}%
  859.   \ece\def{write#1entry}{\writecontentsentry{#1}}%
  860.   \ece\def{writenumbered#1entry}{\writenumberedcontentsentry{#1}}%
  861.   \ece\innernewif{ifrewrite#1file} \csname rewrite#1filetrue\endcsname
  862.   \ece\def{read#1file}{\readcontentsfile{#1}}%
  863. % We provide \opentocfile, \readtocfile, etc., by default.
  864. \definecontentsfile{toc}%
  865. % And `toc' is just the argument to this macro.
  866. \def\opencontentsfile#1{%
  867.   \csname if@#1fileopened\endcsname \else
  868.      \ece{\immediate\openout}{#1file} = \csname #1filebasename\endcsname.#1
  869.      \ece\global{@#1fileopenedtrue}%
  870.   \fi
  871. % \writetocentry#1#2 produces a line in the .toc file that
  872. % looks like:
  873. % \toc#1entry{#2}{page number}
  874. % e.g., 
  875. % \tocchapterentry{Introduction}{2}
  876. % would be written by
  877. % \writetocentry{chapter}{Introduction}
  878. % if the chapter started on page two.
  879. % Thus, #1 is intended to be something like `chapter' or `section', #2
  880. % to be the text of the title.
  881. % Of course, if you want, you can \write\tocfile yourself with whatever
  882. % you like.  In that case, you must also call \opentocfile.
  883. % By the way, it would be wrong to put a \percentchar at the end of the
  884. % output line.  Then, when the .toc file is read, if each line is turned
  885. % into a \leftline, say, there would be no legal breakpoint between the
  886. % boxes, and one extremely long line would result.
  887. % `toc' is the first argument to this; \writetocentry is defined by
  888. % \definecontentsfile.
  889. \def\writecontentsentry#1#2#3{\writenumberedcontentsentry{#1}{#2}{#3}{}}%
  890. % Sometimes you want the control sequence to take another number (e.g.,
  891. % a chapter number) as a parameter.  (Although you can pass anything you
  892. % want as the third parameter, naturally.)  The third parameter is
  893. % expanded at the point of the \writenumberedtocentry, not when the
  894. % \write actually happens.  This makes the usual case---the third
  895. % parameter being \the\someregister---work.
  896. % For example:
  897. % \writenumberedtocentry{chapter}{The second chapter}{2}
  898. % would produce:
  899. % \tocchapterentry{The second chapter}{2}{14}
  900. % if the second chapter started on page 14.
  901. % `toc' is the first argument, as above.
  902. \def\writenumberedcontentsentry#1#2#3#4{%
  903.   \csname ifrewrite#1file\endcsname
  904.     \csname open#1file\endcsname
  905.     \toks0 = {\expandafter\noexpand \csname #1#2entry\endcsname}%
  906.     \def\temp{#3}%
  907.     %
  908.     % Usually #4 is just `\the\register', which we want to expand.  But
  909.     % if it's not a number at all -- e.g., if it's an author's name, we
  910.     % don't want to expand control sequences for accents and the like.
  911.     % So we play some games here.
  912.     \toks2 = \expandafter{#4}%
  913.     \edef\cs{\the\toks2}%
  914.     \edef\@wr{%
  915.       \write\csname #1file\endcsname{%
  916.         \the\toks0 % the \toc...entry control sequence
  917.         {\sanitize\temp}% the text
  918.         \ifx\empty\cs\else {\sanitize\cs}\fi % A secondary number, or nothing:
  919.         {\noexpand\folio}% the page number
  920.       }%
  921.     }%
  922.     \@wr
  923.   \fi
  924.   \ignorespaces
  925. % The entries are read in when the user invokes \readtocfile (which
  926. % should be before the first \writetocentry).  The .toc file is also
  927. % opened for writing (i.e., emptied) here, unless \rewritetocfilefalse.
  928. % You might want to set that if you're reading it in twice to make a
  929. % short contents or some such.
  930. \def\readcontentsfile#1{%
  931.    \edef\temp{%
  932.      \noexpand\testfileexistence[\csname #1filebasename\endcsname]{toc}%
  933.    }\temp
  934.    \if@fileexists
  935.       \input \csname #1filebasename\endcsname.#1\relax
  936.       \csname ifrewrite#1file\endcsname \csname open#1file\endcsname \endif
  937.    \fi
  938. \def\endif{\fi}%
  939. % Here are some sample definitions of the \toc...entry macros.  Perhaps
  940. % you or your book designer can come up with a better way of handling
  941. % contents than leaders.  These definitions are just examples, not
  942. % something you might want to actually use to print a document.
  943. \def\tocchapterentry#1#2{\line{\bf #1 \dotfill\ #2}}%
  944. \def\tocsectionentry#1#2{\line{\quad\sl #1 \dotfill\ \rm #2}}%
  945. \def\tocsubsectionentry#1#2{\line{\qquad\rm #1 \dotfill\ #2}}%
  946.  Cross-references.
  947. % Definitions of references are recorded in \jobname.aux, called
  948. % \auxfile in the macros, which btxmac.tex has opened.
  949. % When a label isn't defined, we only want to complain if
  950. % \xrefwarningtrue; btxmac uses \if@citewarning for this, so we have to
  951. % reuse that name.  We can't just say \let\ifxrefwarning =
  952. % \if@citewarning, since then changes to the latter won't be reflected
  953. % in the former.  On the other hand, we have to have a true \if...
  954. % command, so \if's and \fi's match properly.  What a mess.
  955. \let\ifxrefwarning = \iftrue
  956. \def\xrefwarningtrue{\@citewarningtrue \let\ifxrefwarning = \iftrue}%
  957. \def\xrefwarningfalse{\@citewarningfalse \let\ifxrefwarning = \iffalse}%
  958. % \xref{foo} produces ``p.\thinspace <page#>''.  \xrefn{foo} produces
  959. % ``<page#>''.  \xrdef{foo} produces nothing, but defines the label
  960. % `foo' to be on the current page.
  961. % As usual, it takes two passes to get the cross-references right.  I
  962. % would like to check for labels being defined twice, but I don't know
  963. % how to do that.  If the cross-reference file has been read in, many
  964. % cross-references will be defined that I don't want to complain about.
  965. % It is only if two \xrdef commands are given to the same string that I
  966. % want to complain.  I could define a new control sequence for each
  967. % cross-reference, and check that, but that seems like too high of a
  968. % price to pay.
  969. % \xrlabel{LABEL} expands to a cross-reference internal name.  We append
  970. % an _ character to NAME, to help avoid conflicts.  And we append an `x'
  971. % so that we don't redefine \_ on an empty label.
  972. \begingroup
  973.   % Mike Spivak's MathTime macros for Times Roman fonts changes the
  974.   % catcode of _ to be active.  (From adam@symcom.math.uiuc.edu.)
  975.   \catcode`\_ = 8
  976.   \gdef\xrlabel#1{#1_x}%
  977. \endgroup
  978. % \xrdef{LABEL} defines LABEL to be the current page number.  But we
  979. % don't define the label here, because the page number might be off: if
  980. % this is not the first time through, the label would already be
  981. % defined, and we would redefine it with the wrong information.
  982. \def\xrdef#1{\definexref{#1}{\noexpand\folio}{page}}%
  983. % \definexref{LABEL}{DEFINITION}{CLASS} defines a cross-reference named
  984. % LABEL of label class CLASS to be DEFINITION.  (Or LABEL can be a
  985. % control sequence; it's expanded to get the label text.)  To get a
  986. % possible page number right, we have to write the definition out to the
  987. % auxiliary file, instead of only defining it directly.
  988. \def\definexref#1#2#3{%
  989.   % Remember what we're given; it might be `\@optionalarg', which
  990.   % \readauxfile trashes.  (No loss of generality here, since \csname
  991.   % will fully expand the label anyway.)
  992.   \edef\temp{#1}%
  993.   % Be sure we've read the aux file before we zap it:
  994.   \readauxfile
  995.   % When we read in the aux file next time, define the label:
  996.   \edef\@wr{\noexpand\writeaux{\string\@definelabel{\temp}{#2}{#3}}}%
  997.   \@wr
  998.   \ignorespaces
  999. % \@definelabel{LABEL}{DEFINITION}{CLASS} actually defines LABEL of
  1000. % label class CLASS to be DEFINITION.
  1001. \def\@definelabel#1#2#3{%
  1002.   % Define the control sequence.
  1003.   \expandafter\gdef\csname\xrlabel{#1}\endcsname{#2}%
  1004.   % Remember what kind of label this is, so \ref will know what to do.
  1005.   \global\setproperty{\xrlabel{#1}}{class}{#3}%
  1006. % Typeset a reference to the label #1.
  1007. \def\xrefn#1{%
  1008.   \readauxfile
  1009.   \expandafter \ifx\csname\xrlabel{#1}\endcsname\relax
  1010.     \if@citewarning
  1011.        \message{\linenumber Undefined label `#1'.}%
  1012.     \fi
  1013.     %
  1014.     % Give it a dummy definition, though, to stop multiple error messages.
  1015.     \expandafter\def\csname\xrlabel{#1}\endcsname{%
  1016.       `{\tt
  1017.         \escapechar = -1
  1018.         \expandafter\string\csname#1\endcsname
  1019.       }'%
  1020.     }%
  1021.   \fi
  1022.   \csname\xrlabel{#1}\endcsname % Always produce something.
  1023. % \refn is just a synonym.
  1024. \let\refn = \xrefn
  1025. % One common case: print `p. ' before the page number.
  1026. \def\xref{p.\thinspace\xrefn}%
  1027. % \ref{LABEL} typesets \CLASSword for LABEL's class (if it's defined)
  1028. % and then does \refn on LABEL. But amstex also has a \ref, so tell the
  1029. % user if they try to use \ref and have loaded amsppt.sty.
  1030. % \refs is similar, but puts the letter `s' after the \...word, thus
  1031. % producing (for example) `Figures 1.2' (presumably to be followed by
  1032. % `and~\refn{fig-1.3}').
  1033. \def\@maybewarnref{%
  1034.   \ifundefined{amsppt.sty}%
  1035.     % No amsppt.sty, so just use ours.
  1036.   \else
  1037.     \message{Warning: amsppt.sty and Eplain both define \string\ref. See
  1038.              the Eplain manual.}%
  1039.     % Remember their definition.
  1040.     \let\amsref = \ref
  1041.   \fi
  1042.   \let\ref = \eplainref
  1043.   \ref
  1044. \let\ref = \@maybewarnref
  1045. \def\eplainref{\@generalref{}}%
  1046. \def\refs{\@generalref s}%
  1047. % #1 is the text to follow the \...word, and is supplied by the macros
  1048. % above.  #2 comes from the document, and is the LABEL.
  1049. \def\@generalref#1#2{%
  1050.   \readauxfile
  1051.   \edef\temp{\getproperty{\xrlabel{#2}}{class}}%
  1052.   % If the word for this class is not defined, don't complain.
  1053.   \expandafter\ifx\csname \temp word\endcsname\relax \else
  1054.     % Produce the word.
  1055.     \csname \temp word\endcsname
  1056.     % Add the suffix and then put in a tie before the \refn.  Do not
  1057.     % rely on `~' being defined as a tie.
  1058.     #1\penalty\@M \ 
  1059.   \fi
  1060.   \refn{#2}%
  1061. % References to equations are similar.
  1062. % \eqref{foo} produces ``(<text for equation label foo>)''.
  1063. % \eqdefn{foo} advances \eqnumber, resets \eqsubnumber, and defines
  1064. %   `foo' to be the new number. 
  1065. % \eqsubdefn{foo} advances \eqsubnumber and defines `foo'.  \eqref works
  1066. %   for both equations and subequations,
  1067. % \eqdef{foo} does \eqdefn, then inserts an \eqno and \eqref.
  1068. % \eqsubdef{foo} does \eqsubdefn, then what \eqdef does.
  1069. % The non-``sub'' macros also take an optional argument; if it's
  1070. % present, we use it as the text for the equation label, instead of the
  1071. % various counters.
  1072. % Because there are no page break issues with equations, we can
  1073. % immediately define the control sequence.  But we also need to write
  1074. % the definition out, in case the user wants to forward reference an
  1075. % equation (bad style as that may be).
  1076. % The current equation number is in \eqnumber; we just advance it by one
  1077. % for each \eqdef.  You can handle fancier equation numbers (e.g., ones
  1078. % that include a chapter number) by redefining \eqprint, below, and
  1079. % using your own counters.  We do provide for one level of substructure,
  1080. % since that's more painful to implement than superstructures.
  1081. \newcount\eqnumber
  1082. \newcount\subeqnumber
  1083. % \eqdefn[TEXT]{LABEL} defines LABEL to be TEXT (if it's present),
  1084. % otherwise it advances \eqnumber and defines LABEL to be that.  It
  1085. % doesn't produce anything.
  1086. \def\eqdefn{\@getoptionalarg\@fineqdefn}%
  1087. \def\@fineqdefn#1{%
  1088.   \ifx\@optionalarg\empty
  1089.     \global\advance\eqnumber by 1
  1090.     % We call \eqconstruct here instead of in \@eqdefn because we don't
  1091.     % want to expand it for \eqsubdefn -- \eqsubdefn already includes an
  1092.     % \eqrefn which includes the text of the label which was \eqconstructed.
  1093.     \def\temp{\eqconstruct{\number\eqnumber}}%
  1094.   \else
  1095.     \def\temp{\noexpand\@optionalarg}%
  1096.   \fi
  1097.   % Always reset the current subequation number:
  1098.   \global\subeqnumber = 0
  1099.   % Remember this label, so that we can define subequations:
  1100.   \gdef\@currenteqlabel{#1}%
  1101.   \toks0 = \expandafter{\@currenteqlabel}%
  1102.   % Actually do the definition, taking precautions not to expand \eqrefn
  1103.   % in what we output to the aux file.  \eqrefn expands to many things,
  1104.   % including \count@'s and \edef's and the expansion of \xrlabel, and
  1105.   % it's just a real mess.
  1106.   \begingroup
  1107.     \def\eqrefn{\noexpand\eqrefn}%
  1108.     \edef\temp{\noexpand\@eqdefn{\the\toks0}{\temp}}%
  1109.     \temp
  1110.   \endgroup
  1111. % \eqsubdefn defines its argument as a ``subequation'' of the last \eqdef.
  1112. \def\eqsubdefn#1{%
  1113.   \global\advance\subeqnumber by 1
  1114.   \toks0 = {#1}%
  1115.   % Get the text of the label;
  1116.   \toks2 = \expandafter{\@currenteqlabel}%
  1117.   % We must expand \@currenteqlabel.  We have to not expand
  1118.   % \eqsubreftext here, as well \eqrefn, since the first arg to
  1119.   % \eqsubreftext could also include lots of complicated things.
  1120.   \begingroup
  1121.     \def\eqrefn{\noexpand\eqrefn}%
  1122.     \def\eqsubreftext{\noexpand\eqsubreftext}%
  1123.     \edef\temp{%
  1124.       \noexpand\@eqdefn
  1125.         {\the\toks0}%
  1126.         {\eqsubreftext{\eqrefn{\the\toks2}}{\the\subeqnumber}}%
  1127.     }%
  1128.     \temp           
  1129.   \endgroup
  1130. % \@eqdefn{LABEL}{REF-TEXT} actually handles the equation number
  1131. % definitions and writing to the aux file.
  1132. % In contrast to \xrdef, we define LABEL right away (as REF-TEXT).  We
  1133. % can do this since we know right now what the right equation number is.
  1134. % This eliminates some unnecessary warning.  It also lets the user put
  1135. % \eqdef{} on all equations and have it work, since then \eqref
  1136. % refers to the just-defined new value.
  1137. \def\@eqdefn#1#2{%
  1138.   \definexref{#1}{#2}{eq}%
  1139.   \@definelabel{#1}{#2}{eq}%
  1140. % \eqdef{LABEL} defines LABEL, with \eqdefn, then prints it.  We allow
  1141. % an optional argument to explicitly specify the text which we define
  1142. % the label as.
  1143. \def\eqdef{\@getoptionalarg\@fineqdef}%
  1144. \def\@fineqdef{%
  1145.   \toks0 = \expandafter{\@optionalarg}%
  1146.   \edef\temp{\noexpand\@eqdef{\noexpand\eqdefn[\the\toks0]}}%
  1147.   \temp
  1148. % \eqsubdef is to \eqdef as \eqsubdefn is to \eqdefn.  No optional
  1149. % argument allowed here.
  1150. \def\eqsubdef{\@eqdef\eqsubdefn}%
  1151. % \@eqdef{DEFN-CMD}{LABEL} defines LABEL, using DEFN-CMD.  Then it
  1152. % inserts an \eqno (unless it's called when an \eqno would be invalid).
  1153. % Then it prints the newly-defined value using \eqprint.
  1154. \def\@eqdef#1#2{%
  1155.   #1{#2}% Define the label.
  1156.   \@maybedisableeqno
  1157.   \eqno \eqref{#2}% Print the text.
  1158.   \@mayberestoreeqno
  1159.   \ignorespaces
  1160. % If we are in an alignment or some other inner place, \eqno won't work.
  1161. \let\@mayberestoreeqno = \relax
  1162. \def\@maybedisableeqno{%
  1163.   \ifinner
  1164.     \global\let\eqno = \relax
  1165.     \global\let\@mayberestoreeqno = \@restoreeqno
  1166.   \fi
  1167. % This makes `\eqno' mean \eqno again.
  1168. \let\@primitiveeqno = \eqno
  1169. \def\@restoreeqno{%
  1170.   \global\let\eqno = \@primitiveeqno
  1171.   \global\let\@mayberestoreeqno = \empty
  1172. % \eqrefn{LABEL} produces the text for the equation label LABEL, or
  1173. % something suitable if LABEL is undefined.  (It possibly issues a
  1174. % warning in the latter case as well.)
  1175. \let\eqrefn = \xrefn
  1176. % \eqref{LABEL} is the usual way to refer to equation labels; it calls
  1177. % \eqprint on the text of LABEL.
  1178. \def\eqref#1{\eqprint{\eqrefn{#1}}}%
  1179. % \eqconstruct{EQ-TEXT} constructs an equation number, i.e., the text to
  1180. % be defined as the value of a label.
  1181. \let\eqconstruct = \identity
  1182. % \eqprint{EQ-TEXT} produces the typeset equation number EQ-TEXT.
  1183. \def\eqprint#1{(#1)}%
  1184. % \eqsubreftext{EQ-TEXT}{SUBEQ-TEXT} produces the text of a subequation
  1185. % reference.  (\eqprint is later called on the result of this to produce
  1186. % output for subequations; I didn't define any \subeqprint.)
  1187. \def\eqsubreftext#1#2{#1.#2}%
  1188.  Indexing.
  1189. % \defineindex{PREFIX} defines an index with ``prefix'' PREFIX.  The
  1190. % prefix is used to construct the output filename and the various
  1191. % commands.  We just define all the index commands for this index to
  1192. % call the general commands with PREFIX.
  1193. \let\extraidxcmdsuffixes = \empty
  1194. \outer\def\defineindex#1{%
  1195.   \def\@idxprefix{#1}%
  1196.   % Define the indexing commands for this prefix. 
  1197.   \for\@idxcmd:=,marked,submarked,name%
  1198.                 \extraidxcmdsuffixes\do
  1199.     \@defineindexcmd\@idxcmd
  1200.   % Allocate a stream for the output.
  1201.   \ece\innernewwrite{@#1indexfile}%
  1202.   % And a conditional to test whether we've opened the file.
  1203.   \ece\innernewif{if@#1indexfileopened}%
  1204. % \@defineindexcmd{SUFFIX} defines both silent and non-silent index
  1205. % command for prefix \@idxprefix with suffix SUFFIX.  That is, we define
  1206. % both `\@idxprefix dxSUFFIX' and `\s\@idxprefix dxSUFFIX' to call the
  1207. % corresponding generic command with \@idxprefix.  \silentindexentry is
  1208. % used to decide whether we should ignore following spaces.
  1209. \newif\ifsilentindexentry
  1210. \def\@defineindexcmd#1{%
  1211.   \@defineoneindexcmd{s}{#1}\silentindexentrytrue
  1212.   \@defineoneindexcmd{}{#1}\silentindexentryfalse
  1213. % \@defineoneindexcmd{PREFIX}{SUFFIX}{PRECALL} does just one silent or
  1214. % non-silent commands.  We define the command `\@@PREFIXidxSUFFIX' to do
  1215. % PRECALL, then define \@idxprefix, then call \@idxgetrange with an
  1216. % argument of `\@@{,s}idxSUFFIX'.  (So far every indexing command 
  1217. % should allow a range.  If not, you could redefine `\@@{,s}idxSUFFIX'
  1218. % after this macro is called.)
  1219. \def\@defineoneindexcmd#1#2#3{%
  1220.   \toks@ = {#3}%
  1221.   \edef\temp{%
  1222.     \def
  1223.       % We have to restrict expansion because the generic (\@@...)
  1224.       % commands will be defined after the first call to \defineindex.
  1225.       % Not expanding the user (\idx...) commands is unnecessary unless
  1226.       % the user has defined some new commands, but may as well be cautious.
  1227.       \expandonce\csname#1\@idxprefix dx#2\endcsname % e.g., \idx or \sidxname.
  1228.       {\def\noexpand\@idxprefix{\@idxprefix}% define \@idxprefix
  1229.        % call, e.g., \@@idx or \@@sidxname:
  1230.        \expandonce\csname @@#1idx#2\endcsname
  1231.       }%
  1232.     \def
  1233.       \expandonce\csname @@#1idx#2\endcsname{% e.g., \@@idx
  1234.         % First do PRECALL.
  1235.         \the\toks@
  1236.         % Then call \@idxgetrange with, e.g., \@idx or \@sidxname as its arg.
  1237.         \noexpand\@idxgetrange\expandonce\csname @#1idx#2\endcsname
  1238.       }%
  1239.   \temp
  1240. % \@idxwrite{TERM}{PAGENO} writes a general index entry for TERM on page
  1241. % PAGENO to the index file `\@idxprefix indexfile'.  We open the stream
  1242. % as `\indexfilebasename.\@idxprefix dx' if it isn't already open.
  1243. \let\indexfilebasename = \jobname
  1244. \def\@idxwrite#1#2{%
  1245.   % Be sure the file is opened.
  1246.   \csname if@\@idxprefix indexfileopened\endcsname \else
  1247.     \expandafter\immediate\openout\csname @\@idxprefix indexfile\endcsname =
  1248.       \indexfilebasename.\@idxprefix dx
  1249.     \expandafter\global\csname @\@idxprefix indexfileopenedtrue\endcsname
  1250.   \fi
  1251.   % Save the index term.
  1252.   \def\temp{#1}%
  1253.   % Write the index term and page number.
  1254.   \edef\@wr{%
  1255.     \expandafter\write\csname @\@idxprefix indexfile\endcsname{%
  1256.       \string\indexentry
  1257.       {\sanitize\temp}%
  1258.       {\noexpand#2}%
  1259.     }%
  1260.   \@wr
  1261.   % Marginalize the index term, if desired.
  1262.   \ifindexproofing \insert\@indexproof{\indexproofterm{#1}}\fi
  1263.   % We just appended at least one non-discardable item (namely, the
  1264.   % whatsit from the \write) to the current list.  So in case glue comes
  1265.   % next (not unlikely), be sure we don't inadvertently make that glue a
  1266.   % valid breakpoint, if it wouldn't have been without us.
  1267.   \hookrun{afterindexterm}%
  1268.   % This is the end of the index entry processing.  If this was a silent
  1269.   % entry, ignore following spaces.
  1270.   \ifsilentindexentry \expandafter\ignorespaces\fi
  1271. % If this conditional is true, we output the index terms on the page
  1272. % where they occur.
  1273. \newif\ifindexproofing
  1274. % We need a new insertion class to collect the proofed terms.
  1275. \newinsert\@indexproof
  1276. \dimen\@indexproof = \maxdimen                  % No limit on number of terms.
  1277. \count\@indexproof = 0  \skip\@indexproof = 0pt % They take up no space.
  1278. % This actually typesets the proofed term.  We don't go to any lengths
  1279. % to provide nice-looking output; since the term might have all kinds of
  1280. % weird characters in it, we just dump it in the smallest standard
  1281. % Computer Modern typewriter font.
  1282. % We put the term in an \hbox, even though that might make the output
  1283. % run off the page, since we don't really need to see all of it, and
  1284. % I think it's better to opt for simplicity -- one term per line.
  1285. \font\indexprooffont = cmtt8
  1286. \def\indexproofterm#1{\hbox{\strut \indexprooffont #1}}%
  1287. % If \output doesn't use \makeheadline, or redefines it, it's up to the
  1288. % new \output to call \indexproofunbox.
  1289. \let\@plainmakeheadline = \makeheadline
  1290. \def\makeheadline{%
  1291.   \indexproofunbox
  1292.   \@plainmakeheadline
  1293. % We want to put the proof index terms in the margin, outside the
  1294. % printed area. So if \outsidemargin (for odd pages) and \insidemargin
  1295. % (for even pages) are undefined, we define them (both) to be the default
  1296. % TeX margin -- one inch + \hoffset.
  1297. \def\indexsetmargins{%
  1298.   \ifx\undefined\outsidemargin
  1299.     \dimen@ = 1in
  1300.     \advance\dimen@ by \hoffset
  1301.     \edef\outsidemargin{\the\dimen@}%
  1302.     \let\insidemargin = \outsidemargin
  1303.   \fi
  1304. % We always put the terms in the right-hand margin, so long terms run
  1305. % off the page, instead of into the text.
  1306. \def\indexproofunbox{%
  1307.   \ifvoid\@indexproof\else
  1308.     \indexsetmargins
  1309.     \rlap{%
  1310.       \kern\hsize
  1311.       \ifodd\pageno \kern\outsidemargin \else \kern\insidemargin \fi
  1312.       \vbox to 0pt{\unvbox\@indexproof\vss}%
  1313.     }%
  1314.   \fi
  1315. % \@idxgetrange\CS parses an optional argument which, if present, should
  1316. % be either `begin' or `end', marking the beginning or ending of a range
  1317. % for the index entry.  If we find this, we set the appropriate one of
  1318. % \@idxrangestr.  Then we call \CS.
  1319. % If the optional argument is `see' or `seealso' we read another
  1320. % argument, namely, the entry to see.
  1321. \def\idxrangebeginword{begin}%
  1322. \def\idxbeginrangemark{(}% the corresponding magic char to go in the idx file
  1323. \def\idxrangeendword{end}%
  1324. \def\idxendrangemark{)}%
  1325. \def\idxseecmdword{see}%
  1326. \def\idxseealsocmdword{seealso}%
  1327. \newif\if@idxsee
  1328. \let\@idxseenterm = \relax
  1329. \def\idxpagemarkupcmdword{pagemarkup}%
  1330. \let\@idxpagemarkup = \relax
  1331. \def\@idxgetrange#1{%
  1332.   \let\@idxrangestr = \empty
  1333.   \let\@afteridxgetrange = #1%
  1334.   \@getoptionalarg\@finidxgetopt
  1335. \def\@finidxgetopt{%
  1336.   \for\@idxarg:=\@optionalarg\do{%
  1337.     % These are ordered by my guess at frequency of use.
  1338.     \expandafter\@idxcheckpagemarkup\@idxarg=,%
  1339.     %
  1340.     \ifx\@idxarg\idxrangebeginword
  1341.       \def\@idxrangestr{\idxencapoperator\idxbeginrangemark}%
  1342.     \else
  1343.       \ifx\@idxarg\idxrangeendword
  1344.         \def\@idxrangestr{\idxencapoperator\idxendrangemark}%
  1345.       \else
  1346.         \ifx\@idxarg\idxseecmdword
  1347.           \def\@idxpagemarkup{indexsee}%
  1348.           \@idxseetrue
  1349.         \else
  1350.           \ifx\@idxarg\idxseealsocmdword
  1351.             \def\@idxpagemarkup{indexseealso}%
  1352.             \@idxseetrue
  1353.           \else
  1354.              \ifx\@idxpagemarkup\relax
  1355.                \errmessage{Unrecognized index option `\@idxarg'}%
  1356.              \fi
  1357.           \fi
  1358.         \fi
  1359.       \fi
  1360.     \fi
  1361.   \@afteridxgetrange
  1362. % Check for a command of the form `pagemarkup=\cmd', and if found, set
  1363. % \@idxpagemarkup to `cmd'.
  1364. \def\@idxcheckpagemarkup#1=#2,{%
  1365.   \def\temp{#1}%
  1366.   \ifx\temp\idxpagemarkupcmdword
  1367.     \if ,#2, % If #2 is empty, complain.
  1368.       \errmessage{Missing markup command to `pagemarkup'}%
  1369.     \else
  1370.       % Remove a trailing =.
  1371.       \def\temp##1={##1}%
  1372.       \edef\@idxpagemarkup{\temp\string#2}%
  1373.     \fi
  1374.   \fi
  1375. % \@idxtokscollect uses \@idxmaintoks as the token list for the main
  1376. % part of an index entry and \@idxsubtoks for the subpart.  Then it
  1377. % calls \@idxwrite.
  1378. \def\idxsubentryseparator{!}%
  1379. \def\idxencapoperator{|}%
  1380. \def\idxmaxpagenum{99999}%
  1381. \newtoks\@idxmaintoks
  1382. \newtoks\@idxsubtoks
  1383. \def\@idxtokscollect{%
  1384.   % Remember the subentry.
  1385.   \edef\temp{\the\@idxsubtoks}%
  1386.   % We want to expand the conditions, but not the terms.  The index
  1387.   % entry starts simply with \@idxmaintoks and \@idxsubtoks.
  1388.   \edef\@indexentry{%
  1389.     \the\@idxmaintoks
  1390.     \ifx\temp\empty\else \idxsubentryseparator\the\@idxsubtoks \fi
  1391.     \@idxrangestr
  1392.   % If this is a `see' or `see also' entry, we need to read one more
  1393.   % arg.  We use a giant page number so the entry will be last (for the
  1394.   % benefit of `see also's).  MakeIndex rejects page numbers >=1000.
  1395.   \if@idxsee
  1396.     \@idxseefalse % Reset so the next term won't be a `see'.
  1397.     \edef\temp{\noexpand\@finidxtokscollect{\idxmaxpagenum}}%
  1398.   \else
  1399.     \def\temp{\@finfinidxtokscollect\folio}%
  1400.   \fi
  1401.   \temp
  1402. % \@finidxtokscollect{PAGENO}{REAL-TERM} reads the final term for
  1403. % see/see also entries.  We do not check if the person has put both a
  1404. % range and a see in the same index term (which will confuse makeindex).
  1405. \def\@finidxtokscollect#1#2{%
  1406.   \def\@idxseenterm{#2}%
  1407.   \@finfinidxtokscollect{#1}%
  1408. % \@finfinidxtokscollect{PAGENO} writes \@indexentry for page PAGENO.
  1409. % Besides \@indexentry, if \@idxpagemarkup is not \relax we output an
  1410. % index entry \@indexentry|\@idxpagemarkup{PAGENO}.  And if
  1411. % \@idxseenterm is not \relax we output {\@idxseenterm} after the
  1412. % \@idxpagemarkup.  (This will become an argument to the ``markup''
  1413. % command, which will be \indexsee or \indexseealso.)
  1414. \def\@finfinidxtokscollect#1{%
  1415.   % If we've got a page markup command, append it.
  1416.   \ifx\@idxpagemarkup\relax \else
  1417.     \toks@ = \expandafter{\@indexentry}%
  1418.     \edef\@indexentry{\the\toks@ \idxencapoperator \@idxpagemarkup}%
  1419.     \let\@idxpagemarkup = \relax
  1420.   \fi
  1421.   % If we've got an argument to the ``page markup'' command, append it.
  1422.   \ifx\@idxseenterm\relax \else
  1423.     \toks@ = \expandafter{\@indexentry}%
  1424.     \edef\@indexentry{\the\toks@{\sanitize\@idxseenterm}}%
  1425.     \let\@idxseenterm = \relax
  1426.   \fi
  1427.   % Finally, write what we've constructed.
  1428.   \expandafter\@idxwrite\expandafter{\@indexentry}{#1}%
  1429. % \@idxcollect{MAIN}{SUB} sets up the token registers
  1430. % \@idx{main,sub}toks, then calls \@idxtokscollect.  This is convenient
  1431. % for some of the macros below.
  1432. \def\@idxcollect#1#2{%
  1433.   \@idxmaintoks = {#1}%
  1434.   \@idxsubtoks = {#2}%
  1435.   \@idxtokscollect
  1436. % Following are the TeX macros that correspond to the commands
  1437. % that actually appear in the document.
  1438. % \@idx{TERM} produces TERM in the output and then makes the index entry
  1439. % for TERM as usual.  We don't allow a [SUBTERM] here since then we
  1440. % would lose spaces after the command, which would be very inconvenient.
  1441. % As with all our index commands, we've already defined \@idxprefix (in
  1442. % \idx or whatever), to save passing it around, and we've looked for a
  1443. % range argument before TERM.
  1444. \def\@idx#1{%
  1445.   #1% Produce TERM as output.
  1446.   \@idxcollect{#1}{}%
  1447. % \@sidx{TERM}[SUBTERM] produces an index entry TERM and no output.  If
  1448. % SUBTERM is present, this is a subentry.  (At the moment, I don't
  1449. % provide for subsubentries, since I've never needed that.)
  1450. \def\@sidx#1{\@idxmaintoks = {#1}\@getoptionalarg\@finsidx}%
  1451. \def\@finsidx{%
  1452.   \@idxsubtoks = \expandafter{\@optionalarg}%
  1453.   \@idxtokscollect
  1454. % \@idxconstructmarked{TOKS-REG}\CS{TERM}
  1455. \def\idxsortkeysep{@}% This `@' is catcode 11, but it doesn't matter.
  1456. \def\@idxconstructmarked#1#2#3{%
  1457.   \toks@ = {#2}% The control sequence.
  1458.   \toks2 = {#3}% The term.
  1459.   % Construct TERM@\CS{TERM} as the string to write.
  1460.   \edef\temp{\the\toks2 \idxsortkeysep \the\toks@{\the\toks2}}%
  1461.   % Save it in TOKS-REG.
  1462.   #1 = \expandafter{\temp}%
  1463. % \@idxmarked\CS{TERM} outputs \CS{TERM} and then calls the main part of
  1464. % \@sidxmarked.
  1465. \def\@idxmarked#1#2{%
  1466.   #1{#2}% Produce \CS{TERM} as output.
  1467.   \@idxconstructmarked\@idxmaintoks{#1}{#2}%
  1468.   \@idxsubtoks = {}%
  1469.   \@idxtokscollect
  1470. % \@sidxmarked\CS{TERM}[SUBTERM] outputs an index entry sorted by TERM
  1471. % but producing \CS{TERM}.
  1472. \def\@sidxmarked#1#2{%
  1473.   \@idxconstructmarked\toks@{#1}{#2}%
  1474.   \edef\temp{{\the\toks@}}%
  1475.   \expandafter\@sidx\temp
  1476. % \@idxsubmarked{TERM}\CS{SUBTERM} is like \@idxmarked, except that it's
  1477. % SUBTERM that's marked instead of TERM.
  1478. \def\@idxsubmarked#1#2#3{%
  1479.   #1 #2{#3}% produce `TERM \CS{SUBTERM} as output.
  1480.   \@sidxsubmarked{#1}{#2}{#3}%
  1481. % \@sidxsubmarked{TERM}\CS{SUBTERM} is to \@sidxmarked as \@idxsubmarked
  1482. % is to \@idxmarked.
  1483. \def\@sidxsubmarked#1#2#3{%
  1484.   \@idxmaintoks = {#1}%
  1485.   \@idxconstructmarked\@idxsubtoks{#2}{#3}%
  1486.   \@idxtokscollect
  1487. % \@idxcollectname{FIRST}{LAST} puts `LAST, FIRST' into \temp. (Well,
  1488. % we use \idxnameseparator instead of hardwiring `, '.) If FIRST is
  1489. % empty, don't include the separator.
  1490. \def\idxnameseparator{, }% as in `Tachikawa, Elizabeth'
  1491. \def\@idxcollectname#1#2{%
  1492.   \def\temp{#1}%
  1493.   \ifx\temp\empty
  1494.     \toks@ = {}%
  1495.   \else
  1496.     \toks@ = {\idxnameseparator #1}%
  1497.   \fi
  1498.   \toks2 = {#2}%
  1499.   \edef\temp{\the\toks2 \the\toks@}%
  1500. % \@idxname{FIRST}{LAST} also produces `FIRST LAST' in the output and an
  1501. % index entry for `LAST, FIRST'.
  1502. \def\@idxname#1#2{%
  1503.   #1 #2% Separate the names by a space in the output.
  1504.   \@idxcollectname{#1}{#2}%
  1505.   \expandafter\@idxcollect\expandafter{\temp}{}%
  1506. % \@sidxname{FIRST}{LAST}[SUBTERM] is to \@sidx as \@idxname is to
  1507. % \@idx.
  1508. \def\@sidxname#1#2{%
  1509.   \@idxcollectname{#1}{#2}%
  1510.   \expandafter\@sidx\expandafter{\temp}%
  1511. % Now we come to actually producing the index, i.e., implementing the
  1512. % formatting commands that MakeIndex outputs.
  1513. % \readindexfile is responsible for formatting and printing the index.
  1514. % It reads \indexfilebasename.ind.  We implement the same commands that
  1515. % LaTeX does.  I suppose we could allow for different indices having
  1516. % different basenames, but I can't imagine when that would be useful.
  1517. \let\indexfonts = \relax
  1518. \def\readindexfile#1{%
  1519.   \edef\@idxprefix{#1}%
  1520.   % Does the output file exist?
  1521.   \testfileexistence[\indexfilebasename]{\@idxprefix nd}%
  1522.   \iffileexists \begingroup
  1523.     % If no \begin or \end, define them. The argument will be `{theindex}'.
  1524.     \ifx\begin\undefined
  1525.       \def\begin##1{\@beginindex}%
  1526.       \let\end = \@gobble
  1527.     \fi
  1528.     %
  1529.     % Read the file:
  1530.     \input \indexfilebasename.\@idxprefix nd
  1531.     % 
  1532.     % \doublecolumns isn't affected by groups.
  1533.     \singlecolumn
  1534.   \endgroup
  1535.   \else
  1536.     \message{No index file \indexfilebasename.\@idxprefix nd.}%
  1537.   \fi
  1538. % Here's the default for `\begin{theindex}', if \begin isn't defined.
  1539. \def\@beginindex{%
  1540.   % Define the commands MakeIndex outputs.
  1541.   \let\item = \@indexitem
  1542.   \let\subitem = \@indexsubitem
  1543.   \let\subsubitem = \@indexsubsubitem
  1544.   % Set up the default formatting:
  1545.   \indexfonts
  1546.   \doublecolumns
  1547.   \parindent = 0pt
  1548.   % Let the user override the defaults.
  1549.   \hookrun{beginindex}%
  1550. % MakeIndex puts \indexspace between groups in the ind file.
  1551. \let\indexspace = \bigbreak
  1552. % You can make \afterindexterm appear after the term and before the
  1553. % first page with the following in the ist file:
  1554. % delim_0 "\\afterindexterm "
  1555. % delim_1 "\\afterindexterm "
  1556. % delim_2 "\\afterindexterm "
  1557. \let\afterindexterm = \quad
  1558. % Top-level index entries start with \item.
  1559. \newskip\aboveindexitemskipamount  \aboveindexitemskipamount = 0pt plus2pt
  1560. \def\aboveindexitemskip{\vskip\aboveindexitemskipamount}%
  1561. \def\@indexitem{\begingroup
  1562.   \@indexitemsetup
  1563.   \leftskip = 0pt
  1564.   \aboveindexitemskip
  1565.   \penalty-100 % Encourage page breaks before items.
  1566.   % But forbid page breaks after items, in case a subitem follows.
  1567.   \def\par{\endgraf\endgroup\nobreak}%
  1568. % Secondary index entries.
  1569. \def\@indexsubitem{%
  1570.   \@indexitemsetup
  1571.   \leftskip = 1em
  1572. % And tertiary entries.
  1573. \def\@indexsubsubitem{%
  1574.   \@indexitemsetup
  1575.   \leftskip = 2em
  1576. % Common setup for the formatting.
  1577. \def\@indexitemsetup{%
  1578.   \par
  1579.   \hangindent = 1em
  1580.   \raggedright
  1581.   \hyphenpenalty = 10000
  1582.   \hookrun{indexitem}%
  1583. % \indexsee{TERM}{PAGENO} ignores PAGENO, and says `See TERM'.
  1584. \def\seevariant{\it}%
  1585. \def\indexseeword{See}%
  1586. \def\indexsee#1#2{{\seevariant \indexseeword\ }#1}%
  1587. % \indexseealso{TERM}{PAGENO} is similar.
  1588. \def\indexseealsowords{see also}%
  1589. \def\indexseealso#1#2{{\seevariant \indexseealsowords\ }#1}%
  1590. % We provide one index by default; commands are \idx, \sidx, etc.
  1591. \defineindex{i}%
  1592.  Justification of multiple input lines.
  1593. % You use these by saying 
  1594. % {\flushright 
  1595. % <flush right text>
  1596. % and similarly for \flushleft and \center.  The command must be
  1597. % embedded in a group.  The lines are set in paragraphs as usual, i.e.,
  1598. % blank lines start a new paragraph (by virtue of the
  1599. % \blanklineskipamount vertical glue being inserted).
  1600. % \environment ... \endenvironment isn't appropriate in this case, since
  1601. % these ``environments'' can't be nested.
  1602. \begingroup
  1603.   \catcode `\^^M = \active %
  1604.   \gdef\flushleft{%
  1605.     \def\@endjustifycmd{\@endflushleft}%
  1606.     \def\@eoljustifyaction{\null\hfil\break}%
  1607.     \let\@firstlinejustifyaction = \relax
  1608.     \@startjustify %
  1609.   \gdef\flushright{%
  1610.     \def\@endjustifycmd{\@endflushright}%
  1611.     \def\@eoljustifyaction{\break\null\hfil}%
  1612.     \def\@firstlinejustifyaction{\hfil\null}%
  1613.     \@startjustify %
  1614.   \gdef\center{%
  1615.     \def\@endjustifycmd{\@endcenter}%
  1616.     \def\@eoljustifyaction{\hfil\break\null\hfil}%
  1617.     \def\@firstlinejustifyaction{\hfil\null}%
  1618.     \@startjustify %
  1619.   % We do this before starting any of the justification commands.
  1620.   \gdef\@startjustify{%
  1621.     \parskip = 0pt
  1622.     \catcode`\^^M = \active %
  1623.     \def^^M{\futurelet\next\@finjustifyreturn}%
  1624.     %
  1625.     % \@eateol is called at the beginning of each justified paragraph.
  1626.     \def\@eateol##1^^M{%
  1627.       \def\temp{##1}%
  1628.       \@firstlinejustifyaction %
  1629.       \ifx\temp\empty\else \temp^^M\fi %
  1630.     }%
  1631.     \expandafter\aftergroup\@endjustifycmd %
  1632.     \checkenv \environmenttrue %
  1633.     \par\noindent %
  1634.     \@eateol %
  1635.   % If the next thing is a ^^M, insert \blanklineskipamount glue.  Then
  1636.   % do \@eoljustifyaction (which each justification command defines).
  1637.   \gdef\@finjustifyreturn{%
  1638.     \@eoljustifyaction %
  1639.     \ifx\next^^M%
  1640.       % Insert extra glue when the \@end... command does the \par.
  1641.       \def\par{\endgraf\vskip\blanklineskipamount \global\let\par = \endgraf}%
  1642.       \@endjustifycmd %
  1643.       % Get back into horizontal mode for the next line.
  1644.       \noindent %
  1645.       \@firstlinejustifyaction %
  1646.     \fi %
  1647. \endgroup
  1648. \def\@endflushleft{\unpenalty{\parfillskip = 0pt plus1fil\par}\ignorespaces}%
  1649. \def\@endflushright{% Remove the \hfil\null\break we just put on.
  1650.    \unskip \setbox0=\lastbox \unpenalty
  1651.    % We have fil glue at the left of the line; \parfillskip shouldn't
  1652.    % affect that.
  1653.    {\parfillskip = 0pt \par}\ignorespaces
  1654. \def\@endcenter{% Remove the \hfil\null\break we just put on.
  1655.    \unskip \setbox0=\lastbox \unpenalty
  1656.    % We have fil glue at the left of the line; \parfillskip must balance it.
  1657.    {\parfillskip = 0pt plus1fil \par}\ignorespaces
  1658.  Automatically-columnated tables.
  1659. % \makecolumns N/K: organizes the entries on the following N lines into
  1660. % K columns.  If N is too small, some text beyond the end of the table
  1661. % will be incorporated into the table, probably producing an error
  1662. % message.  If N is too large, some of the entries will appear after the
  1663. % table, probably looking very out of place.
  1664. % You can adjust the position of the table on the page by changing
  1665. % \parindent (space to the left of the block) and \hsize (distance from
  1666. % the left margin to the right of the block).  (No doubt inside a
  1667. % group.)  And you can allow a page break above the valign by changing
  1668. % \abovecolumnspenalty.
  1669. \newcount\abovecolumnspenalty   \abovecolumnspenalty = 10000
  1670. \newcount\@linestogo         % Lines remaining to process.
  1671. \newcount\@linestogoincolumn % Lines remaining in column.
  1672. \newcount\@columndepth       % Number of lines in a column.
  1673. \newdimen\@columnwidth       % Width of each column.
  1674. \newtoks\crtok  \crtok = {\cr}%
  1675. \newcount\currentcolumn
  1676. % The space matches an end-of-line that will probably be there.
  1677. \def\makecolumns#1/#2: {\par \begingroup
  1678.    % Set \@columndepth to the number of items we will put in a column:
  1679.    % (N - 1) / K.
  1680.    \@columndepth = #1
  1681.    \advance\@columndepth by #2
  1682.    \advance\@columndepth by -1
  1683.    \divide \@columndepth by #2
  1684.    \@linestogoincolumn = \@columndepth
  1685.    \@linestogo = #1
  1686.    % We start in the first column.
  1687.    \currentcolumn = 1
  1688.    \def\@endcolumnactions{%
  1689.       \ifnum \@linestogo<2 
  1690.          \the\crtok \egroup \endgroup \par % End \valign and \makecolumns.
  1691.       \else
  1692.          % We've done one more line out of the total.
  1693.          \global\advance\@linestogo by -1
  1694.          % 
  1695.          % How many left in the column?
  1696.          % 
  1697.          \ifnum\@linestogoincolumn<2
  1698.             % End this column, that was the last line.
  1699.             \global\advance\currentcolumn by 1
  1700.             \global\@linestogoincolumn = \@columndepth
  1701.             \the\crtok
  1702.          \else
  1703.             % Still got more lines to go.
  1704.             &\global\advance\@linestogoincolumn by -1
  1705.          \fi
  1706.       \fi
  1707.    }%
  1708.    % Set up to read the table.
  1709.    % 
  1710.    \makeactive\^^M
  1711.    \letreturn \@endcolumnactions
  1712.    % 
  1713.    % Figure out how wide our columns are going to be; each column has
  1714.    % exactly the same template, so we can use the feature described on
  1715.    % p.241 of the TeXbook for repeating preambles.
  1716.    % 
  1717.    \@columnwidth = \hsize
  1718.      \advance\@columnwidth by -\parindent
  1719.      \divide\@columnwidth by #2
  1720.    \penalty\abovecolumnspenalty
  1721.    \noindent % It's not a paragraph (usually).
  1722.    \valign\bgroup
  1723.      &\hbox to \@columnwidth{\strut \hsize = \@columnwidth ##\hfil}\cr
  1724.      %
  1725.      % The next end-of-line starts everything going.
  1726. % \numberedfootnote is like plain TeX's \footnote, but automatically
  1727. % numbered.  When you want to reset the footnote number, say
  1728. % \footnotenumber = 0.
  1729. % We also provide for more general formatting than \footnote:
  1730. %   \footnotemarkseparation is the space between the reference mark and
  1731. %     the footnote text;
  1732. %  \interfootnoteskip is the space between footnotes;
  1733. %  \everyfootnote is expanded just before we typeset the footnote.
  1734. % The dimensions of the footnote rule are controlled by
  1735. % \footnoterulewidth and \footnoteruleheight (the depth is always zero);
  1736. % the space after the rule is \belowfootnoterulespace.
  1737. \newcount\footnotenumber
  1738. \newdimen\footnotemarkseparation \footnotemarkseparation = .5em
  1739. \newskip\interfootnoteskip \interfootnoteskip = 0pt
  1740. \newtoks\everyfootnote
  1741. \newdimen\footnoterulewidth \footnoterulewidth = 2in
  1742. \newdimen\footnoteruleheight \footnoteruleheight = 0.4pt
  1743. \newdimen\belowfootnoterulespace \belowfootnoterulespace = 2.6pt
  1744. \let\@plainfootnote = \footnote
  1745. \let\@plainvfootnote = \vfootnote
  1746. \def\vfootnote#1{\insert\footins\bgroup
  1747.   \interlinepenalty\interfootnotelinepenalty
  1748.   \splittopskip\ht\strutbox % top baseline for broken footnotes
  1749.   \advance\splittopskip by \interfootnoteskip
  1750.   \splitmaxdepth\dp\strutbox
  1751.   \floatingpenalty\@MM
  1752.   \leftskip\z@skip \rightskip\z@skip \spaceskip\z@skip \xspaceskip\z@skip
  1753.   \everypar = {}%
  1754.   \parskip = 0pt % because of the vskip
  1755.   % Even if typesetting in multicolumns, do footnotes in normal page width.
  1756.   % (We don't have any provision in the output routine for having
  1757.   % footnotes per column, anyway.)
  1758.   \ifnum\@numcolumns > 1 \hsize = \@normalhsize \fi
  1759.   \the\everyfootnote
  1760.   \vskip\interfootnoteskip
  1761.   \indent\llap{#1\kern\footnotemarkseparation}\footstrut\futurelet\next\fo@t
  1762. \def\footnoterule{\dimen@ = \footnoteruleheight
  1763.   \advance\dimen@ by \belowfootnoterulespace
  1764.   \kern-\dimen@
  1765.   \hrule width\footnoterulewidth height\footnoteruleheight depth0pt
  1766.   \kern\belowfootnoterulespace
  1767.   \vskip-\interfootnoteskip
  1768. \def\numberedfootnote{%
  1769.   \global\advance\footnotenumber by 1
  1770.   \@plainfootnote{$^{\number\footnotenumber}$}%
  1771.  Margins.
  1772. % TeX's primitives determine the type area.  But some users prefer to
  1773. % think in terms of margins.  These definitions allow one to say, for
  1774. % example, `\topmargin = 2in', instead of `\voffset=1in\advance\vsize by
  1775. % -1in'.  Constructions like `\advance\topmargin by 1in' give an error
  1776. % message, though, since \topmargin is not a parameter.  Instead, the
  1777. % macro \advancetopmargin has to be used.
  1778. \newdimen\paperheight \paperheight = 11in
  1779. \def\topmargin{\afterassignment\@finishtopmargin \dimen@}%
  1780. \def\@finishtopmargin{%
  1781.   \dimen2 = \voffset        % Remember the old \voffset.
  1782.   \voffset = \dimen@ \advance\voffset by -1in
  1783.   \advance\dimen2 by -\voffset    % Compute the change in \voffset.
  1784.   \advance\vsize by \dimen2    % Change type area accordingly.
  1785. \def\advancetopmargin{%
  1786.   \dimen@ = 0pt \afterassignment\@finishadvancetopmargin \advance\dimen@
  1787. \def\@finishadvancetopmargin{%
  1788.   \advance\voffset by \dimen@
  1789.   \advance\vsize by -\dimen@
  1790. \def\bottommargin{\afterassignment\@finishbottommargin \dimen@}%
  1791. \def\@finishbottommargin{%
  1792.   \@computebottommargin        % Result in \dimen2.
  1793.   \advance\dimen2 by -\dimen@    % Compute the change in the bottom margin.
  1794.   \advance\vsize by \dimen2    % Change the type area.
  1795. \def\advancebottommargin{%
  1796.   \dimen@ = 0pt \afterassignment\@finishadvancebottommargin \advance\dimen@
  1797. \def\@finishadvancebottommargin{%
  1798.   \advance\vsize by -\dimen@
  1799. % Find the current bottom margin, putting the result in \dimen2.
  1800. \def\@computebottommargin{%
  1801.   \dimen2 = \paperheight    % The total paper size.
  1802.   \advance\dimen2 by -\vsize    % Less the text size.
  1803.   \advance\dimen2 by -\voffset    % Less the offset at the top.
  1804.   \advance\dimen2 by -1in    % Less the default offset.
  1805. \newdimen\paperwidth \paperwidth = 8.5in
  1806. \def\leftmargin{\afterassignment\@finishleftmargin \dimen@}%
  1807. \def\@finishleftmargin{%
  1808.   \dimen2 = \hoffset        % Remember the old \hoffset.
  1809.   \hoffset = \dimen@ \advance\hoffset by -1in
  1810.   \advance\dimen2 by -\hoffset    % Compute the change in \hoffset.
  1811.   \advance\hsize by \dimen2    % Change type area accordingly.
  1812. \def\advanceleftmargin{%
  1813.   \dimen@ = 0pt \afterassignment\@finishadvanceleftmargin \advance\dimen@
  1814. \def\@finishadvanceleftmargin{%
  1815.   \advance\hoffset by \dimen@
  1816.   \advance\hsize by -\dimen@
  1817. \def\rightmargin{\afterassignment\@finishrightmargin \dimen@}%
  1818. \def\@finishrightmargin{%
  1819.   \@computerightmargin        % Result in \dimen2.
  1820.   \advance\dimen2 by -\dimen@    % Compute the change in the right margin.
  1821.   \advance\hsize by \dimen2    % Change the type area.
  1822. \def\advancerightmargin{%
  1823.   \dimen@ = 0pt \afterassignment\@finishadvancerightmargin \advance\dimen@
  1824. \def\@finishadvancerightmargin{%
  1825.   \advance\hsize by -\dimen@
  1826. % Find the current right margin, putting the result in \dimen2.
  1827. \def\@computerightmargin{%
  1828.   \dimen2 = \paperwidth        % The total paper size.
  1829.   \advance\dimen2 by -\hsize    % Less the text size.
  1830.   \advance\dimen2 by -\hoffset    % Less the offset at the left.
  1831.   \advance\dimen2 by -1in    % Less the default offset.
  1832.  Double column output.
  1833. % \doublecolumns begins double column output.  It can be called
  1834. % in the midst of a page.  \singlecolumn restores single column 
  1835. % output.  (It would be wrong to require \enddoublecolumns, because 
  1836. % often one wants double column mode to continue to the end of 
  1837. % the document.)
  1838. % The basic approach is that of Appendix E of the TeXbook, p.417.
  1839. % David Guichard made significant improvements to my original implementation.
  1840. % The glue here (the default is intended to be one linespace) is inserted
  1841. % before double columns start, and after they end.
  1842. \newskip\abovecolumnskip \abovecolumnskip = \bigskipamount
  1843. \newskip\belowcolumnskip \belowcolumnskip = \bigskipamount
  1844. % Space between the columns. It can be changed as desired.
  1845. \newdimen\gutter \gutter = 2pc
  1846. % These registers are needed for dealing with switching back and forth.
  1847. \newbox\@partialpage
  1848. \newdimen\@columnhsize
  1849. \newdimen\@normalhsize
  1850. \newdimen\@normalvsize
  1851. \newtoks\previousoutput
  1852. % Some synonymous ways to refer to multiple column modes.
  1853. \def\quadcolumns{\@columns4}%
  1854. \def\triplecolumns{\@columns3}%
  1855. \def\doublecolumns{\@columns2}%
  1856. \def\begincolumns#1{\ifcase#1\relax \or \singlecolumn \or \@columns2 \or
  1857.                             \@columns3 \or \@columns4 \else \relax \fi}%
  1858. \let\endcolumns = \singlecolumn
  1859. \let\@ndcolumns = \relax
  1860. % Set this by default so \vfootnote can unconditionally inspect it.
  1861. \chardef\@numcolumns = 1
  1862. % Start typesetting with #1 columns.
  1863. \def\@columns#1{%
  1864.   \@ndcolumns
  1865.   \let\@ndcolumns = \@endcolumns
  1866.   \chardef\@numcolumns = #1
  1867.   \par                     % Shouldn't start in horizontal mode.
  1868.   \previousoutput = \expandafter{\the\output}%
  1869.   % Figure out how wide the columns should be -- for n columns,
  1870.   % decrement by n - 1 gutters.
  1871.   \@columnhsize = \hsize
  1872.   \count@ = \@numcolumns
  1873.   \advance\count@ by -1
  1874.   \advance\@columnhsize by -\count@\gutter
  1875.   \divide\@columnhsize by \@numcolumns
  1876.   % Set up to grab the page so far and save it in \@partialpage.
  1877.   \output = {\global\setbox\@partialpage =
  1878.     \vbox{\unvbox255\vskip\abovecolumnskip}%
  1879.   % \pagegoal is the size that TeX will make \box255.  We want a box
  1880.   % exactly the size of the current height of the page, i.e., \pagetotal.
  1881.   \pagegoal = \pagetotal
  1882.   % Expand the \output we just defined.
  1883.   \eject
  1884.   % Reset \output to prepare for the first real page break.
  1885.   \output = {\@columnoutput}%
  1886.   \@normalhsize = \hsize
  1887.   \@normalvsize = \vsize
  1888.   \hsize = \@columnhsize
  1889.   % Compute \vsize based on what's already on the page
  1890.   % and the number of columns. Also change the mag factor for insertions.
  1891.   \advance\vsize by -\ht\@partialpage
  1892.   \advance\vsize by -\ht\footins
  1893.   \ifvoid\footins\else \advance\vsize by -\skip\footins \fi
  1894.   \multiply\count\footins by \@numcolumns
  1895.   \advance\vsize by -\ht\topins
  1896.   \ifvoid\topins\else \advance\vsize by -\skip\topins \fi
  1897.   \multiply\count\topins by \@numcolumns
  1898.   \global\vsize = \@numcolumns\vsize
  1899. % When this is invoked box 255 contains just the right amount of
  1900. % material, whether triggered by an output routine or a change in the
  1901. % number of columns. Because columns have to contain an integral number
  1902. % of lines of type, we take a bit of care with balancing the heights of
  1903. % the columns to prevent either losing material or having a very short
  1904. % last column.
  1905. % when a page ends due to \bye or \eject, box 255 will contain lots of
  1906. % white space, so the columns will not look balanced. To fix this use
  1907. % \singlecolumn before ending the page.
  1908. \def\@columnsplit{%
  1909.   \splittopskip = \topskip
  1910.   \splitmaxdepth = \baselineskip
  1911.   % \dimen@ will be the height that the double-column material on this
  1912.   % page should have, i.e., the height of the page (\singlecolumvsize)
  1913.   % minus single-column material, which includes insertions.  (If you
  1914.   % want your insertions to respect the columns, you will have to
  1915.   % change the output routine.)  If you add more insertions, they
  1916.   % should be taken into account both here and in \singlecolumn.
  1917.   % Unfortunately, we lose on flexible glue because we must
  1918.   % \vsplit to a <dimen>.
  1919.   \dimen@ = \ht255
  1920.     \divide\dimen@ by \@numcolumns
  1921.  % Split the long scroll into columns.
  1922.  \begingroup
  1923.     % We do not want to see underfull \vbox messages unless the final
  1924.     % page is underfull.
  1925.     \vbadness = 10000
  1926.     %
  1927.     % The first (leftmost) column.
  1928.     \global\setbox1 = \vsplit255 to \dimen@  \global\wd1 = \hsize
  1929.     %
  1930.     % The second column.
  1931.     \global\setbox3 = \vsplit255 to \dimen@  \global\wd3 = \hsize
  1932.     %
  1933.     \ifnum\@numcolumns > 2
  1934.       % The third column, if requested.
  1935.       \global\setbox5 = \vsplit255 to \dimen@ \global\wd5 = \hsize
  1936.     \fi
  1937.     \ifnum\@numcolumns > 3
  1938.       % The fourth column, likewise if requested.
  1939.       \global\setbox7 = \vsplit255 to \dimen@ \global\wd7 = \hsize
  1940.     \fi
  1941.   \endgroup
  1942.   % Preserve what's left over.
  1943.   \setbox0 = \box255
  1944.   % Set up \box255 with the real output page, as the previous output
  1945.   % routine expects.
  1946.   \global\setbox255 = \vbox{%
  1947.     \unvbox\@partialpage
  1948.     \ifcase\@numcolumns \relax\or\relax
  1949.       \or \hbox to \@normalhsize{\box1\hfil\box3}%
  1950.       \or \hbox to \@normalhsize{\box1\hfil\box3\hfil\box5}%
  1951.       \or \hbox to \@normalhsize{\box1\hfil\box3\hfil\box5\hfil\box7}%
  1952.     \fi
  1953.   % Save what's left over in a private register before calling their
  1954.   % output routine.
  1955.   \setbox\@partialpage = \box0
  1956. % Our output routine splits the columns and then calls the previous one.
  1957. \def\@columnoutput{%
  1958.   \@columnsplit
  1959.   \hsize = \@normalhsize % Local to \output's group.
  1960.   \vsize = \@normalvsize
  1961.   \the\previousoutput
  1962.   % Put back what didn't fit.
  1963.   \unvbox\@partialpage
  1964.   \penalty\outputpenalty
  1965.   % The correct vsize is the original vsize times the
  1966.   % number of columns.
  1967.   \global\vsize = \@numcolumns\@normalvsize
  1968. % Go back to single-column typesetting.  Assume \doublecolumns has
  1969. % been called.
  1970. \def\singlecolumn{%
  1971.   \@ndcolumns
  1972.   \chardef\@numcolumns = 1
  1973.   \vskip\belowcolumnskip
  1974.   \nointerlineskip
  1975. \def\@endcolumns{%
  1976.   \global\let\@ndcolumns = \relax
  1977.   \par % Shouldn't start in horizontal mode.
  1978.   \global\output = {\global\setbox1 = \box255}%
  1979.   \pagegoal = \pagetotal
  1980.   \eject                    % Exercise the page builder, i.e., \output.
  1981.   \global\setbox255 = \box1 % Retrieve what the fake \output set.
  1982.   % \box255 now has the double-column material.  On the page where we
  1983.   % switch back to one column, the double-column material might not
  1984.   % fill up the page.  We want to split whatever is there.
  1985.   \@columnsplit
  1986.   \global\vsize = \@normalvsize
  1987.   \global\hsize = \@normalhsize
  1988.   \global\output = \expandafter{\the\previousoutput}%
  1989.   \ifvoid\topins\else\topinsert\unvbox\topins\endinsert\fi
  1990.   \unvbox255
  1991. % We don't have any way to force a column eject, since the \output
  1992. % routine is only prepared to split up a full page of material. Instead,
  1993. % we provide the following as a guess at enough space to fill up the
  1994. % current column.
  1995. \def\columnfill{%
  1996.   \dimen@ = \@normalvsize
  1997.   \advance\dimen@ by -\pagetotal
  1998.   \kern\dimen@
  1999. \let\wlog = \@plainwlog
  2000. \catcode`@ = \@eplainoldatcode
  2001. \def\fmtname{eplain}%
  2002. \def\eplain{t}%
  2003. {\edef\plainversion{\fmtversion}%
  2004.  \xdef\fmtversion{REPLACE-WITH-VERSION: REPLACE-WITH-DAY-MONTH-YEAR (and plain \plainversion)}%
  2005. % Local variables:
  2006. % page-delimiter: "^% \f"
  2007. % End:
  2008.